#include "mg_Rs485Protocol.h"
#include "mg_Rs485Config.h"
#include "mg_child_device.h"
#include "mg_Device.h"
#include "mg_timer.h"
#include "string.h"
#include "mg_Lcd_Driver.h"
#include "../scene.h"
#include "mg_file.h"
#include "mg_crc.h"

volatile uint8_t gFrameNum;//帧序列号
volatile bool SendDataNow;//现在是否正在发数据

PROTOCOL_TX_REG 			Protocol_Tx_Reg;//注册数据
PROTOCOL_CMD 				Protocol_Tx_Cmd;//基本命令格式
PROTOCOL_DATA 				Protocol_Tx_Data;//基本数据格式
STRUCT_DEV_UPDATA 			DevUpData[DEVICE_CHANNEL_MAX];//设备状态更新缓存

#define DO_BUS_RBUF_MAX_SIZE			2048			//接收缓存数组大小
#define DO_BUS_SBUF_MAX_SIZE			1024			//发送缓存数组大小

volatile STRUCT_RS485_RECEIVE	RS485RxData;			//接收数据结构体
volatile uint8_t Recv_data_fifo[DO_BUS_RBUF_MAX_SIZE];	//缓存数组
volatile uint8_t Recv_data_frame_len = 0;				//接收一帧数据长度
volatile int32_t Recv_data_fifo_len = 0;				//当前有数据长度

volatile STRUCT_RS485_SEND		RS485TxData;			//发送数据结构体
volatile uint8_t Send_data_fifo[DO_BUS_SBUF_MAX_SIZE];	//缓存数组
volatile uint8_t Send_data_frame_len = 0;				//接收一帧数据长度
volatile int32_t Send_data_fifo_len = 0;				//当前有数据长度


//将16进制数转化为字符串
void HexToStr(uint8_t *pbDest, char *pbSrc, int nLen)
{
	char    ddl, ddh;
	int i;

	for (i = 0; i<nLen; i++)
	{
		ddh = 48 + pbSrc[i] / 16;
		ddl = 48 + pbSrc[i] % 16;
		if (ddh > 57) ddh = ddh + 7;
		if (ddl > 57) ddl = ddl + 7;
		pbDest[i * 2] = ddh;
		pbDest[i * 2 + 1] = ddl;
	}

	pbDest[nLen * 2] = '\0';
}
//判断单个UTF8字符长度
int Get_UTF8_Byte_Size(const unsigned char Input)
{
	unsigned char c = Input;
	// 0xxxxxxx 返回0
	// 10xxxxxx 不存在
	// 110xxxxx 返回2
	// 1110xxxx 返回3
	// 11110xxx 返回4
	// 111110xx 返回5
	// 1111110x 返回6
	if (c< 0x80) return 1;
	if (c >= 0x80 && c<0xC0) return -1;
	if (c >= 0xC0 && c<0xE0) return 2;
	if (c >= 0xE0 && c<0xF0) return 3;
	if (c >= 0xF0 && c<0xF8) return 4;
	if (c >= 0xF8 && c<0xFC) return 5;
	if (c >= 0xFC) return 6;
	return -1;
}
//判断UTF字符串字符个数
uint8_t Get_UTF8_Str_Size(unsigned char *pInput, uint8_t InputLen)
{
	uint8_t TempLen,ByteLen=0;
	uint8_t HaveChinese = 0;
	int ByteSize;
	TempLen = InputLen;
	while (TempLen>0 && pInput[InputLen - TempLen] != 0)
	{
		ByteSize = Get_UTF8_Byte_Size(pInput[InputLen - TempLen]);
		if (ByteSize > 0)
		{
			if (ByteSize == 3)HaveChinese = 1;
			ByteLen++;
		}
		else
		{
			break;
		}
		TempLen -= ByteSize;
	}
	return ByteLen;
}
//返回合理的文字换行格式(两行)
UTF8_TWO_LINE Get_UTF8_Two_Line(unsigned char *pInput, uint8_t InputLen)
{
	UTF8_TWO_LINE DeviceName;
	uint8_t i;
	int ByteSize = 0;
	//换行
	uint8_t TempLen = InputLen, ByteLen = 0;	//字符转义后长度
	uint8_t HaveChinese = 0;		//是否有中文
	while (TempLen>0 && pInput[InputLen - TempLen] != 0)
	{
		ByteSize = Get_UTF8_Byte_Size(pInput[InputLen - TempLen]);
		if (ByteSize > 0)
		{
			if (ByteSize == 3)HaveChinese = 1;
			ByteLen++;
		}
		else
			break;
		TempLen -= ByteSize;
	}

	//赋值名称
	memset(DeviceName.DeviceName1, 0, sizeof(DeviceName.DeviceName1));
	memset(DeviceName.DeviceName2, 0, sizeof(DeviceName.DeviceName2));
	if (HaveChinese)//存在中文
	{
		if (ByteLen <= 3)
		{
			memcpy(DeviceName.DeviceName1, pInput, InputLen);
		}
		else
		{
			ByteSize = 0;
			for (i = 0; i < ByteLen / 2; i++)
				ByteSize += Get_UTF8_Byte_Size(pInput[ByteSize]);
			memcpy(DeviceName.DeviceName1, pInput, ByteSize);
			memcpy(DeviceName.DeviceName2, &pInput[ByteSize], InputLen - ByteSize);
		}
	}
	else//只有英文或符号
	{
		uint8_t HavePause = 0;
		for (i = 0; i < ByteLen; i++)
		{
			if (pInput[i] == ' ')//存在空格
			{
				if (i < 10)
				{
					memcpy(DeviceName.DeviceName1, pInput, i);
					memcpy(DeviceName.DeviceName2, &pInput[i + 1], InputLen - i - 1);
				}
				else
				{
					memcpy(DeviceName.DeviceName1, pInput, 10);
					memcpy(DeviceName.DeviceName2, &pInput[10], InputLen - 10);
				}
				HavePause = 1;
				break;
			}
		}
		if (!HavePause)//没有空格
		{
			if (ByteLen > 10)
			{
				memcpy(DeviceName.DeviceName1, pInput, 10);
				memcpy(DeviceName.DeviceName2, &pInput[10], InputLen - 10);
			}
			else
			{
				memcpy(DeviceName.DeviceName1, pInput, ByteLen);
			}
		}
	}

	return DeviceName;
}

//===================================< 发送数据 >=============================================
//帧序列号加1
void FrameNumAdd(void)
{
	gFrameNum++;//帧序列低 	 	
}
//根据波特率计算退避基时间(以下以MS为单位)(1个比特位的时间40us)
uint8_t MacBackBaseTimeChose(enumBaudType aBaud)
{
	uint8_t temp = 0;

	switch (aBaud)
	{
	case BAUD_38400:
		temp = 30;
		break;
	case BAUD_19200:
		temp = 40;
		break;
	case BAUD_9600:
		temp = 135;
		break;
	default:
		temp = 40;
		break;
	}
	return temp;
}
//取的随机数(40~100ms)
unsigned char RS485GetBackTime(void)
{
	unsigned char tTmp;
	tTmp = rand();//获取随机数
	//退避时间等于：随机数＋设备地址＋一个基时间	
	tTmp = (tTmp % 20) + 40 + Sys.Addr % 40;

	return tTmp;
}
//总线忙检测
void RS485ExtiIsr(void)
{
	RS485TxData.Busy = true;
}
//串口发送
void RS485Send(unsigned char *p, unsigned char length)
{
	SendDataNow = true;
	Uart1_Send(p, length);
	/*USART_ReceiveData(USART1);*/
	SendDataNow = false;
	UsartValuInit();
}
//停止发送进程
void RS485SendProcessStop(void)
{
	RS485SendTimDisable();
	MessageFlag[MSG_RESEND_DATA] = OFF;
	RS485TxData.AckEnble = false;
	RS485TxData.Stat = false;
}
//发退避时钟使能(发送进程使能)
void RS485SendTimerReady(void)
{
	RS485TxData.ReTxTimeCnt = 0;
	RS485TxData.WaitCnt = USART_WAIT_CNT;//退避等待次数
	RS485TxData.Busy = false;   //总线状态

	if (RS485TxData.Buf[0] == FRAME_Request)//注册报文需要一直重发
	{
		//重发时间间隔计算(10ms/per)
		if (RS485TxData.ReTxCount <= 1475)
		{
			RS485TxData.ReTxTime = USART_RESEND_WAIT_TIME + RS485TxData.ReTxCount * 4;
			RS485TxData.ReTxCount++;
		}
		else
		{
			RS485TxData.ReTxTime = 60000;//10分钟
		}
	}
	else//其他报文重发4次加上，原始报文一共5次
	{
		if (RS485TxData.ReTxCount < RS485TxData.ReTxNum)
		{
			RS485TxData.ReTxTime = USART_RESEND_WAIT_TIME + RS485TxData.ReTxCount * 4;
			RS485TxData.ReTxCount++;
		}
		else
		{
			RS485SendProcessStop();
		}
	}
	if (RS485TxData.Buf[0] == FRAME_Ask)
	{
		RS485TxData.WaitTime = MacBackBaseTimeChose(USART_BAUDRATE);//应答包时间固定
	}
	else
	{
		RS485TxData.WaitTime = RS485GetBackTime();//退避时间	
	}
	//使能发送时钟(us)
	RS485SendTimEnable(RS485TxData.WaitTime);

}
//发送数据推入缓存
int32_t Mobus_Send_Data_Push(uint8_t *buf, uint8_t len, bool ack, uint8_t SendCntMax)
{
	int32_t i = Send_data_fifo_len;
	uint8_t *ptr = (uint8_t *)Send_data_fifo;

	if (i + 2 + len >= DO_BUS_SBUF_MAX_SIZE-50)//预留50字节，防止死掉
	{
		return -1;
	}
	ptr[i + 0] = len;					//数据长度
	ptr[i + 1] = ack<<7 | SendCntMax;	//Bit7:是否需要应答|Bit0-4发送次数
	memcpy(i + ptr + 2, buf, len);		//接收数据
	i += 2 + len;						//数据长度增加
	Send_data_fifo_len = i;				//数据长度

	return i;
}
//发送数据从缓存中删除
int32_t Mobus_Send_Data_Pop(void)
{
	int32_t i = Send_data_fifo_len;
	uint8_t *ptr = (uint8_t *)Send_data_fifo;
	uint8_t len = ptr[0];

	if (2 + len > i)
	{
		i = 0;
	}
	else
	{
		memcpy(ptr, ptr + 2 + len, DO_BUS_SBUF_MAX_SIZE - (2 + len));
		i -= 2 + len;
	}
	Send_data_fifo_len = i;

	return i;
}
//检测是否有数据需要发送,有则发送
bool Mobus_SendProcess(void)
{
	uint8_t len;
	uint8_t *buf = (uint8_t *)Send_data_fifo;	//数组
	uint8_t i = Send_data_fifo_len;				//长度
	
	if(RS485TxData.Stat == ON)return false;//发送状态
	len = buf[0];							//数据长度
	if(i == 0)//缓存无数据
	{
		return false;
	}
	if(len >= RS485_BUF_LEN)
	{
		RS485TxData.Stat = OFF;
		Mobus_Send_Data_Pop();
		return false;
	}
	RS485TxData.Stat = ON;
	RS485TxData.Length = len;		//长度
	for(i=0; i<len; i++)
	{
		RS485TxData.Buf[i] = buf[i + 2]; //缓存
	}
	RS485TxData.AckEnble = buf[1] >> 7;//应答使能
	RS485TxData.ReTxNum = buf[1] & 0x7F;//重发总数
	RS485TxData.ReTxCount = 0;		//重发计数器
	RS485SendTimerReady();
	
	Mobus_Send_Data_Pop();					//删除发送数据
	return true;
}
//发送数据进程(退避定时器在滴答中断调用)最小定时40ms
uint8_t SendDatasTemp[RS485_BUF_LEN];
void RS485SendProcess_Timer(void)
{
	uint8_t i;

	if (RS485TxData.BackTimerEnble != true)return;// 退避定时器使能
	if (RS485TxData.BackTimeCnt != 0){ RS485TxData.BackTimeCnt--; return; }
	RS485TxData.BackTimeCnt = RS485TxData.WaitTime;

	if (RS485TxData.Busy == true)
	{
		RS485TxData.Busy = false;
		if (RS485TxData.WaitCnt != 0)
		{
			RS485TxData.WaitCnt--;
		}
		else
		{
			RS485TxData.WaitCnt = 0;
			RS485TxData.ReTxTimeCnt = 0;
			if (RS485TxData.AckEnble == true)
			{
				//关闭发送时钟(us)
				MessageFlag[MSG_RESEND_DATA] = ON; //重发数据
				RS485SendTimDisable();
			}
			else
			{
				RS485SendProcessStop(); //结束
			}
		}
	}
	else
	{
		FrameNumAdd();//帧序列号加一
		RS485TxData.Buf[1] = VERSION_CODE;//帧序列高
		RS485TxData.Buf[3] = gFrameNum;//帧序列低
		RS485TxData.Buf[4] = Sys.Addr;
		memcpy(SendDatasTemp, RS485TxData.Buf, RS485TxData.Length);
		SendDatasTemp[RS485TxData.Length - 1] = Get_CRC8(SendDatasTemp, (uint8_t)(RS485TxData.Length - 1));
		RS485Send((uint8_t *)SendDatasTemp, RS485TxData.Length);
		RS485TxData.WaitCnt = 0;
		RS485TxData.ReTxTimeCnt = 0;
		if (RS485TxData.AckEnble == true)
		{
			//关闭发送时钟(us)
			RS485SendTimDisable();
		}
		else
		{
			RS485SendProcessStop();//结束
		}
	}
}
//等待应答计时进程(在滴答时钟中调用)10ms
void RS485ReSendProcessTime(void)
{
	if (RS485TxData.Stat == OFF)return;
	if (RS485TxData.AckEnble != true)return;//应答使能 
	if (RS485TxData.BackTimerEnble == true)return;

	RS485TxData.ReTxTimeCnt++;
	if (RS485TxData.ReTxTimeCnt < RS485TxData.ReTxTime)return;
	RS485TxData.ReTxTimeCnt = 0;
	MessageFlag[MSG_RESEND_DATA] = ON;
}
//重发发数进程(在主循环中调用)
void RS485ReSendProcess(void)
{
	if (MessageFlag[MSG_RESEND_DATA] != ON)return;
	RS485SendTimerReady();//发数
	MessageFlag[MSG_RESEND_DATA] = OFF;
}
//===================================< 接收数据 >=============================================
//复位指针
void UsartValuInit(void)
{
	RS485RxData.ptrBufWrite = 0;
	RS485RxData.ptrBufRead = 0;
	RS485RxData.BytCnt = 0;//接收字节计数
	RS485RxData.TimeCnt = 0;
	RS485RxData.TimeEnble = false;
	SendDataNow = false;
	RS485RxData.RxLock = false;
}
//将接受到的数据放入缓存
int32_t do_bus_recv_push(uint8_t *buf, uint8_t len)
{
	int32_t i = Recv_data_fifo_len;
	uint8_t *ptr = (uint8_t *)Recv_data_fifo;

	if (i + 2 + len >= DO_BUS_RBUF_MAX_SIZE - 50)//预留50字节，防止死掉
	{
		printf("Moorgen INFO : Rs485 buffer PoPu is FULL.\n");
		return -1;
	}
	ptr[i + 0] = len;                  //数据长度
	ptr[i + 1] = 0;                    //标记
	memcpy(i + ptr + 2, buf, len);     //接收数据
	i += 2 + len;                      //数据长度增加
	Recv_data_fifo_len = i;         //数据长度
	return i;
}
//删除用过的数据
int32_t do_bus_recv_pop(void)
{
	int32_t i = Recv_data_fifo_len;
	uint8_t *ptr = (uint8_t *)Recv_data_fifo;
	uint8_t len = ptr[0];

	if (2 + len > i) {
		i = 0;
	}
	else
	{
		memcpy(ptr, ptr + 2 + len, DO_BUS_RBUF_MAX_SIZE - (2 + len));
		i -= 2 + len;
	}
	Recv_data_fifo_len = i;
	return i;
}
//验证将要放入缓存的数据
int32_t do_bus_recv(uint8_t *buf, uint32_t len)
{
	uint8_t cmd = buf[0], i;
	uint16_t target = buf[2];
	unsigned char crc = Get_CRC8(buf, len - 1);

	if (crc != buf[len - 1]) //检验
	{
		return -1;
	}
	if (len < FRAME_HEAD_LEN) //长度错误
	{
		return -3;
	}
	if (target != Sys.Addr && target != ADDRESS_Broadcast && cmd != FRAME_GroupBroadcast)
	{
		return -4;
	}
	if (cmd != FRAME_Ask &&
		cmd != FRAME_GroupBroadcast &&
		target == Sys.Addr)
	{
		printf("Moorgen INFO : Rs485 Recieve: ", len);
		for (i = 0; i < len; i++)
		{
			printf("%02X ", buf[i]);
		}
		printf(", Data Len:%d\n", len);

		RS485_Tx_ACK(0);  //回复应答
	}
	return do_bus_recv_push(buf, len);
}
//串口数据放入指定缓存
int32_t usart_recv(void)
{
	volatile uint8_t frame_data[USART_RXDATA_LEN];//缓存数组

	uint8_t len = Recv_data_frame_len;
	memcpy(frame_data, (uint8_t *)RS485RxData.Buf, len);
	return do_bus_recv(frame_data, len);
}
//接收完成定时器(1ms)
void RS485RxOverTimIsr(void)
{
	if (RS485RxData.TimeEnble == false)return;

	RS485RxData.TimeCnt++;
	if (RS485RxData.TimeCnt < USART_RXEND_TIME)return;//当USART_RXEND_TIME时间内没有收到字节，接收结束
	RS485RxData.RxLock = true;
	//保存结束帧长度
	RS485RxData.BytCnt = RS485RxData.ptrBufWrite;//长度
	Recv_data_frame_len = RS485RxData.ptrBufWrite;
	usart_recv();
	//接收完成
	RS485RxData.ptrBufWrite = 0;
	RS485RxData.TimeEnble = false;
	RS485RxData.TimeCnt = 0;
}
//读取一帧数据
bool ReadAPacketFromRxBuf(uint8_t *pData, uint8_t *len)
{
	uint8_t *buf = (uint8_t *)Recv_data_fifo;		//数组
	uint8_t i = Recv_data_fifo_len;		//长度
	*len = buf[0];							//数据长度
	if (i == 0)//缓存无数据
	{
		return false;
	}
	//得到数据
	for (i = 0; i<*len; i++)
	{
		pData[i] = Recv_data_fifo[i + 2];
	}
	UsartValuInit();
	do_bus_recv_pop();
	return true;
}
/*
**********************************************************************
******************************< HT协议 >******************************
**********************************************************************
*/
//===================================<发送帧处理>=======================================
//发送节点请求帧(入网)
void RS485PointSendReg(void)
{
	uint8_t size, dCnt = 0, i = 0, chl = 0;//typeChl=0,
	uint16_t type = Sys.Type;
	//typeChl = Sys.TypeChl;	
	Protocol_Tx_Reg.FrameControl = FRAME_Request;//帧控制
	Protocol_Tx_Reg.FrameNum_H = VERSION_CODE;	//帧序列高
	Protocol_Tx_Reg.dAddress = 0x00;			//目标地址
	Protocol_Tx_Reg.FrameNum_L = gFrameNum;		//帧序列低 
	Protocol_Tx_Reg.NetID = Sys.Addr;			//网络ID|MY_ID
	Protocol_Tx_Reg.Cmd = VERSION_CODE;			//网络控制命令
	Protocol_Tx_Reg.myType[0] = (uint8_t)(type >> 8);
	Protocol_Tx_Reg.myType[1] = (uint8_t)type;
	Protocol_Tx_Reg.Chl.bits.SubAddr = 0;		//设备子地址
	Protocol_Tx_Reg.Chl.bits.ChlMax = Sys.Channal;	//设备总数
	if (Sys.Channal == 1)
	{
		Protocol_Tx_Reg.DataLen = 1;			//数据长度
		Protocol_Tx_Reg.myData[0] = DeviceNumMax;		//可配置通道数
	}
	else if (Sys.Channal <= 8)
	{
		Protocol_Tx_Reg.DataLen = (2 + Sys.Channal * 4);	//数据长度n
		dCnt = 0;
		Protocol_Tx_Reg.myData[dCnt++] = Sys.Channal;	//通道总数//数据
		Protocol_Tx_Reg.myData[dCnt++] = 0x02;			//通道类型
		for (i = 0; i<Sys.Channal; i++)
		{
			chl = (0x01 << i);
			type = DevicChlToType(i);
			Protocol_Tx_Reg.myData[dCnt++] = chl;			//通道(地暖)
			if (i == 0)
				Protocol_Tx_Reg.myData[dCnt++] = DeviceNumMax;	//通道(地暖)
			else
				Protocol_Tx_Reg.myData[dCnt++] = 1;				//通道(地暖)
			Protocol_Tx_Reg.myData[dCnt++] = (uint8_t)(type >> 8);		//设备类型
			Protocol_Tx_Reg.myData[dCnt++] = (uint8_t)type;	//设备类型
		}
	}
	else
	{
		Protocol_Tx_Reg.DataLen = (2 + Sys.Channal * 5);	//数据长度n
		dCnt = 0;
		Protocol_Tx_Reg.myData[dCnt++] = Sys.Channal;	//通道总数//数据
		Protocol_Tx_Reg.myData[dCnt++] = 0x02;			//通道类型
		for (i = 0; i<Sys.Channal; i++)
		{
			chl = (0x01 << i);
			type = DevicChlToType(i);
			Protocol_Tx_Reg.myData[dCnt++] = chl & 0xFF;			//通道(地暖)
			Protocol_Tx_Reg.myData[dCnt++] = chl >> 8;
			if (i == 0)
				Protocol_Tx_Reg.myData[dCnt++] = DeviceNumMax;	//通道(地暖)
			else
				Protocol_Tx_Reg.myData[dCnt++] = 1;				//通道(地暖)
			Protocol_Tx_Reg.myData[dCnt++] = (uint8_t)(type >> 8);		//设备类型
			Protocol_Tx_Reg.myData[dCnt++] = (uint8_t)type;	//设备类型
		}
	}
	size = 10 + Protocol_Tx_Reg.DataLen;
	RS485TxData.Stat = false;
	Mobus_Send_Data_Push((unsigned char *)&Protocol_Tx_Reg, (size + 1), true, 0xff);
}
//面板发送数据帧
void RS485PanelSendData(uint8_t chl, uint8_t dataLen, uint8_t *myData)
{
	uint8_t size, i, *p = Protocol_Tx_Data.myData;

	Protocol_Tx_Data.FrameControl = FRAME_KeyEnable;
	Protocol_Tx_Data.FrameNum_H = VERSION_CODE;	//帧序列高
	Protocol_Tx_Data.dAddress = 0x00;			//目标地址
	Protocol_Tx_Data.FrameNum_L = gFrameNum;	//帧序列低
	Protocol_Tx_Data.NetID = Sys.Addr;
	Protocol_Tx_Data.Chl.bits.SubAddr = chl;		//设备子地址
	Protocol_Tx_Data.Chl.bits.ChlMax = Sys.Channal;	//设备总数
	Protocol_Tx_Data.DataLen = dataLen;
	//数据
	for (i = 0; i<dataLen; i++)
		*p++ = *myData++;
	size = (sizeof(Protocol_Tx_Data)-DATA_SIZE_MAX) + dataLen;
	Mobus_Send_Data_Push((unsigned char *)&Protocol_Tx_Data, (size + 1), true, USART_RESEND_MAX);
}
//发送数据帧
void RS485SendData(uint8_t chl, uint8_t dataLen, uint8_t *myData)
{
	uint8_t size, i, *p = Protocol_Tx_Data.myData;

	Protocol_Tx_Data.FrameControl = FRAME_Data;
	Protocol_Tx_Data.FrameNum_H = VERSION_CODE;	//帧序列高
	Protocol_Tx_Data.dAddress = 0x00;			//目标地址
	Protocol_Tx_Data.FrameNum_L = gFrameNum;	//帧序列低
	Protocol_Tx_Data.NetID = Sys.Addr;
	Protocol_Tx_Data.Chl.bits.SubAddr = chl;		//设备子地址
	Protocol_Tx_Data.Chl.bits.ChlMax = Sys.Channal;	//设备总数
	Protocol_Tx_Data.DataLen = dataLen;
	//数据
	for (i = 0; i<dataLen; i++)
		*p++ = *myData++;
	size = (sizeof(Protocol_Tx_Data)-DATA_SIZE_MAX) + dataLen;
	Mobus_Send_Data_Push((unsigned char *)&Protocol_Tx_Data, (size + 1), true, USART_RESEND_MAX);
}
//从机读数据请求
void RS485ReadInfo(uint8_t chl, uint8_t dataLen, uint8_t *myData)
{
	uint8_t size, i, *p = Protocol_Tx_Data.myData;

	Protocol_Tx_Data.FrameControl = FRAME_SlaveReadInfo;
	Protocol_Tx_Data.FrameNum_H = VERSION_CODE;	//帧序列高
	Protocol_Tx_Data.dAddress = 0x00;     	//目标地址
	Protocol_Tx_Data.FrameNum_L = gFrameNum;	//帧序列低
	Protocol_Tx_Data.NetID = Sys.Addr;
	Protocol_Tx_Data.Chl.bits.SubAddr = chl;	//设备子地址
	Protocol_Tx_Data.Chl.bits.ChlMax = Sys.Channal;	//设备总数
	Protocol_Tx_Data.DataLen = dataLen;

	//数据
	for (i = 0; i<dataLen; i++)
	{
		*p++ = *myData++;
	}
	size = (sizeof(Protocol_Tx_Data)-DATA_SIZE_MAX) + dataLen;

	Mobus_Send_Data_Push((unsigned char *)&Protocol_Tx_Data, (size + 1), true, USART_RESEND_MAX);
}
//从机设置参数上报
void RS485SendInfo(uint8_t chl, uint8_t dataLen, uint8_t *myData)
{
	uint8_t size, i, *p = Protocol_Tx_Data.myData;

	Protocol_Tx_Data.FrameControl = FRAME_MasterReadInfo;
	Protocol_Tx_Data.FrameNum_H = VERSION_CODE;	//帧序列高
	Protocol_Tx_Data.dAddress = 0x00;			//目标地址
	Protocol_Tx_Data.FrameNum_L = gFrameNum;	//帧序列低 
	Protocol_Tx_Data.NetID = Sys.Addr;
	Protocol_Tx_Data.Chl.bits.SubAddr = chl;		//设备子地址
	Protocol_Tx_Data.Chl.bits.ChlMax = Sys.Channal;		//设备总数
	Protocol_Tx_Data.DataLen = dataLen;

	//数据
	for (i = 0; i<dataLen; i++)
	{
		*p++ = *myData++;
	}
	size = (sizeof(Protocol_Tx_Data)-DATA_SIZE_MAX) + dataLen;
	Mobus_Send_Data_Push((unsigned char *)&Protocol_Tx_Data, (size + 1), true, USART_RESEND_MAX);
}
//发送恢复应答
void RS485_Reset_ACK(uint8_t ErrCode)
{
	uint8_t size, *p = &Protocol_Tx_Data.myData[0];

	Protocol_Tx_Data.FrameControl = FRAME_Reset;
	Protocol_Tx_Data.FrameNum_H = VERSION_CODE;	//帧序列高
	Protocol_Tx_Data.dAddress = 0x00;			//目标地址
	Protocol_Tx_Data.FrameNum_L = gFrameNum;	//帧序列低 
	Protocol_Tx_Data.NetID = Sys.Addr;
	Protocol_Tx_Data.Chl.bits.SubAddr = 0;			//设备子地址
	Protocol_Tx_Data.Chl.bits.ChlMax = Sys.Channal;		//设备总数
	Protocol_Tx_Data.DataLen = 1;
	*p++ = ErrCode;

	size = (sizeof(Protocol_Tx_Data)-DATA_SIZE_MAX) + Protocol_Tx_Data.DataLen;

	*p = Get_CRC8((uint8_t *)&Protocol_Tx_Data, size);//CRC8
	RS485Send((uint8_t *)&Protocol_Tx_Data, (size + 1));
}
//发送应答帧
void RS485_Tx_ACK(uint8_t ErrCode)
{
	uint8_t size, *p = &Protocol_Tx_Cmd.myData[0];

	Protocol_Tx_Cmd.FrameControl = FRAME_Ask;
	Protocol_Tx_Cmd.FrameNum_H = VERSION_CODE;	//帧序列高
	Protocol_Tx_Cmd.dAddress = 0x00;			//目标地址
	Protocol_Tx_Cmd.FrameNum_L = gFrameNum;	//帧序列低
	Protocol_Tx_Cmd.NetID = Sys.Addr;
	Protocol_Tx_Cmd.Cmd = SCMD_ASK;
	Protocol_Tx_Cmd.DataLen = 0;
	if (ErrCode>0)
	{
		Protocol_Tx_Cmd.DataLen = 1;
		*p++ = ErrCode;
	}

	size = (sizeof(Protocol_Tx_Cmd)-DATA_SIZE_MAX) + Protocol_Tx_Cmd.DataLen;

	*p = Get_CRC8((uint8_t *)&Protocol_Tx_Cmd, size);//CRC8
	RS485Send((uint8_t *)&Protocol_Tx_Cmd, (size + 1));
}
//发送储存错误
void RS485_Tx_SaveErr(uint8_t ErrCode)
{
	uint8_t size, *p = &Protocol_Tx_Data.myData[0];

	Protocol_Tx_Data.FrameControl = FRAME_SaveError;
	Protocol_Tx_Data.FrameNum_H = VERSION_CODE;	//帧序列高
	Protocol_Tx_Data.dAddress = 0x00;			//目标地址
	Protocol_Tx_Data.FrameNum_L = gFrameNum;	//帧序列低 
	Protocol_Tx_Data.NetID = Sys.Addr;
	Protocol_Tx_Data.Chl.bits.SubAddr = 0;			//设备子地址
	Protocol_Tx_Data.Chl.bits.ChlMax = Sys.Channal;		//设备总数
	Protocol_Tx_Data.DataLen = 2;
	//数据
	*p++ = 1;
	*p++ = ErrCode;

	size = (sizeof(Protocol_Tx_Data)-DATA_SIZE_MAX) + Protocol_Tx_Data.DataLen;
	Mobus_Send_Data_Push((unsigned char *)&Protocol_Tx_Data, (size + 1), true, USART_RESEND_MAX);
}
//查询单个设备状态
void RS485_Get_TFTDeviceState(uint32_t DeviceKeyVol)
{
	uint8_t size, *p = &Protocol_Tx_Data.myData[0];

	Protocol_Tx_Data.FrameControl = FRAME_TFT_ReadInfo;
	Protocol_Tx_Data.FrameNum_H = VERSION_CODE;	//帧序列高
	Protocol_Tx_Data.dAddress = 0x00;			//目标地址
	Protocol_Tx_Data.FrameNum_L = gFrameNum;	//帧序列低 
	Protocol_Tx_Data.NetID = Sys.Addr;
	Protocol_Tx_Data.Chl.bits.SubAddr = 0;			//设备子地址
	Protocol_Tx_Data.Chl.bits.ChlMax = Sys.Channal;		//设备总数
	Protocol_Tx_Data.DataLen = 5;
	*p++ = 0x04;
	if (TFT_Device[DeviceKeyVol].DeviceIsAllocation == true && TFT_Device[DeviceKeyVol].DeviceEventType == 1)
	{
		*p++ = TFT_Device[DeviceKeyVol].TFTSCEQ.TFT_Device.DeviceID.byte.L;
		*p++ = TFT_Device[DeviceKeyVol].TFTSCEQ.TFT_Device.DeviceID.byte.mL;
		*p++ = TFT_Device[DeviceKeyVol].TFTSCEQ.TFT_Device.DeviceID.byte.mH;
		*p++ = TFT_Device[DeviceKeyVol].TFTSCEQ.TFT_Device.DeviceID.byte.H;
	}
	size = (sizeof(Protocol_Tx_Data)-DATA_SIZE_MAX) + Protocol_Tx_Data.DataLen;
	printf("Moorgen INFO : Query TFT for the status of No.%d configured devices\n", DeviceKeyVol);
	Mobus_Send_Data_Push((unsigned char *)&Protocol_Tx_Data, (size + 1), true, USART_RESEND_MAX);
}
//查询所有设备状态
void RS485_Get_AllTFTDeviceState(void)
{
	uint8_t i, count = 0;
	uint8_t size, *p = &Protocol_Tx_Data.myData[0];

	Protocol_Tx_Data.FrameControl = FRAME_TFT_ReadInfo;
	Protocol_Tx_Data.FrameNum_H = VERSION_CODE;	//帧序列高
	Protocol_Tx_Data.dAddress = 0x00;			//目标地址
	Protocol_Tx_Data.FrameNum_L = gFrameNum;	//帧序列低 
	Protocol_Tx_Data.NetID = Sys.Addr;
	Protocol_Tx_Data.Chl.bits.SubAddr = 0;			//设备子地址
	Protocol_Tx_Data.Chl.bits.ChlMax = Sys.Channal;		//设备总数
	*p++ = 0x04;
	for (i = 1; i <= DeviceNumMax; i++)
	{
		if (TFT_Device[i].DeviceIsAllocation == true && TFT_Device[i].DeviceEventType == 1)
		{
			*p++ = TFT_Device[i].TFTSCEQ.TFT_Device.DeviceID.byte.L;
			*p++ = TFT_Device[i].TFTSCEQ.TFT_Device.DeviceID.byte.mL;
			*p++ = TFT_Device[i].TFTSCEQ.TFT_Device.DeviceID.byte.mH;
			*p++ = TFT_Device[i].TFTSCEQ.TFT_Device.DeviceID.byte.H;
			count++;
		}
	}
	if (count == 0)return;
	Protocol_Tx_Data.DataLen = count * 4 + 1;
	size = (sizeof(Protocol_Tx_Data)-DATA_SIZE_MAX) + Protocol_Tx_Data.DataLen;
	printf("Moorgen INFO : Query TFT for the status of all configured devices\n");
	Mobus_Send_Data_Push((unsigned char *)&Protocol_Tx_Data, (size + 1), true, USART_RESEND_MAX);
}
//获取单个设备的设置参数
void RS485_Get_TFTDeviceConfig(uint32_t DeviceKeyVol,uint8_t StartAddr,uint8_t InfoLen)
{
	uint8_t size, *p = &Protocol_Tx_Data.myData[0];

	Protocol_Tx_Data.FrameControl = FRAME_TFT_ReadInfo;
	Protocol_Tx_Data.FrameNum_H = VERSION_CODE;	//帧序列高
	Protocol_Tx_Data.dAddress = 0x00;			//目标地址
	Protocol_Tx_Data.FrameNum_L = gFrameNum;	//帧序列低 
	Protocol_Tx_Data.NetID = Sys.Addr;
	Protocol_Tx_Data.Chl.bits.SubAddr = 0;			//设备子地址
	Protocol_Tx_Data.Chl.bits.ChlMax = Sys.Channal;		//设备总数
	Protocol_Tx_Data.DataLen = 8;
	*p++ = 0x08;
	if (TFT_Device[DeviceKeyVol].DeviceIsAllocation == true && TFT_Device[DeviceKeyVol].DeviceEventType == 1)
	{
		*p++ = TFT_Device[DeviceKeyVol].TFTSCEQ.TFT_Device.DeviceID.byte.L;
		*p++ = TFT_Device[DeviceKeyVol].TFTSCEQ.TFT_Device.DeviceID.byte.mL;
		*p++ = TFT_Device[DeviceKeyVol].TFTSCEQ.TFT_Device.DeviceID.byte.mH;
		*p++ = TFT_Device[DeviceKeyVol].TFTSCEQ.TFT_Device.DeviceID.byte.H;
	}
	*p++ = 2;
	*p++ = StartAddr;
	*p++ = InfoLen;
	size = (sizeof(Protocol_Tx_Data)-DATA_SIZE_MAX) + Protocol_Tx_Data.DataLen;
	printf("Moorgen INFO : Query TFT for the config of No.%d configured devices\n", DeviceKeyVol);
	Mobus_Send_Data_Push((unsigned char *)&Protocol_Tx_Data, (size + 1), true, USART_RESEND_MAX);
}
//TFT设备执行
void RS485_Set_TFTDeviceState(uint32_t DeviceKeyVol)
{
	uint8_t size, *p = &Protocol_Tx_Data.myData[0], j = 0, i;
	uint16_t nType;
	Protocol_Tx_Data.FrameControl = FRAME_TFT_Data;
	Protocol_Tx_Data.FrameNum_H = VERSION_CODE;	//帧序列高
	Protocol_Tx_Data.dAddress = 0x00;			//目标地址
	Protocol_Tx_Data.FrameNum_L = gFrameNum;	//帧序列低 
	Protocol_Tx_Data.NetID = Sys.Addr;
	Protocol_Tx_Data.Chl.bits.SubAddr = 0;			//设备子地址
	Protocol_Tx_Data.Chl.bits.ChlMax = Sys.Channal;		//设备总数

	p[j++] = TFT_Device[DeviceKeyVol].DeviceEventType;	//事件类型
	p[j++] = TFT_Device[DeviceKeyVol].TFTSCEQ.TFT_Scene.DeviceID.byte.L;
	p[j++] = TFT_Device[DeviceKeyVol].TFTSCEQ.TFT_Scene.DeviceID.byte.mL;
	p[j++] = TFT_Device[DeviceKeyVol].TFTSCEQ.TFT_Scene.DeviceID.byte.mH;
	p[j++] = TFT_Device[DeviceKeyVol].TFTSCEQ.TFT_Scene.DeviceID.byte.H;
	if (TFT_Device[DeviceKeyVol].DeviceEventType == 1)//事件类型为设备执行
	{
		nType = TFT_Device[DeviceKeyVol].TFTSCEQ.TFT_Device.DeviceType;
		printf("Moorgen INFO :nType Device is 0x%02X \n", nType);
		switch (nType)
		{
		case DEVIC_TYPE_LIGHT://普通灯
		case DEVIC_TYPE_LIGHT_KNX://普通灯
		case DEVIC_TYPE_LIGHT_ZIGBEE://Zigbee 普通灯
		case DEVIC_TYPE_CTLIGHT://CT灯带
		case DEVIC_TYPE_CTLIGHT1_ZIGBEE://Zigbee CT灯带
		case DEVIC_TYPE_CTLIGHT2_ZIGBEE://Zigbee CT灯带
		case DEVIC_TYPE_CTLIGHT3_ZIGBEE://Zigbee CT灯带
		case DEVIC_TYPE_CTLIGHT4_ZIGBEE://Zigbee CT灯带
		case DEVIC_TYPE_ADJUSTLIGHT://调光灯
		case DEVIC_TYPE_ADJUSTLIGHT_KNX://调光灯
		case DEVIC_TYPE_ADJUSTLIGHT1_ZIGBEE://Zigbee 调光灯
		case DEVIC_TYPE_ADJUSTLIGHT2_ZIGBEE://Zigbee 调光灯
		case DEVIC_TYPE_ADJUSTLIGHT3_ZIGBEE://Zigbee 调光灯
		case DEVIC_TYPE_ADJUSTLIGHT4_ZIGBEE://Zigbee 调光灯
		case DEVIC_TYPE_ADJUSTLIGHT5_ZIGBEE://Zigbee 调光灯
		case DEVIC_TYPE_ADJUSTLIGHT6_ZIGBEE://Zigbee 调光灯
		case DEVIC_TYPE_ADJUSTLIGHT7_ZIGBEE://Zigbee 调光灯
		case DEVIC_TYPE_ADJUSTLIGHT8_ZIGBEE://Zigbee 调光灯
		case DEVIC_TYPE_ADJUSTLIGHT9_ZIGBEE://Zigbee 调光灯
		case DEVIC_TYPE_ADJUSTLIGHT10_ZIGBEE://Zigbee 调光灯
		case DEVIC_TYPE_RIGUANGDENG://日光灯
		case DEVIC_TYPE_GROUP_LIGHT://普通灯组
		case DEVIC_TYPE_GROUP_ADJUSTLIGHT://调光灯组
		case DEVIC_TYPE_GROUP_CTLIGHT://CT灯组
			p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status;
			if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_OFF ||
				TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_ON)//开/关
			{
				p[j++] = 0;
			}
			else if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_VALUE)//调光
			{
				p[j++] = 1;
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[0];
			}
			else if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_TEMP)//调色温
			{
				p[j++] = 1;
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[1];
			}
			break;
		case DEVIC_TYPE_CTLIGHT_KNX:
			p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status;
			if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_OFF ||
				TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_ON)//开/关
			{
				p[j++] = 0;
			}
			else if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_VALUE)//调光
			{
				p[j++] = 1;
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[0];
			}
			else if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_TEMP_KNX)//调色温
			{
				p[j++] = 2;
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[1];
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[2];
			}
			break;
		case DEVIC_TYPE_TONINGLIGHT://调色灯
		case DEVIC_TYPE_TONINGLIGHT_KNX://调色灯
		case DEVIC_TYPE_RGBWLIGHT://RGBW灯
		case DEVIC_TYPE_RGBWLIGHT_KNX://RGBW灯
		case DEVIC_TYPE_GROUP_TONINGLIGHT://调色灯组
			p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status;
			if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_OFF ||
				TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_ON)//开/关
			{
				p[j++] = 0;
			}
			else if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_RGB)//调色
			{
				p[j++] = 3;
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[0];
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[1];
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[2];
			}
			else if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_RGBW)//带W调色
			{
				p[j++] = 4;
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[0];
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[1];
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[2];
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[3];
			}
			break;
		case DEVIC_TYPE_RGBCWLIGHT://RGBCW灯
		case DEVIC_TYPE_GROUP_RGBCW_HSB://RGBCW灯组
			p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status;
			if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_OFF ||
				TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_ON)//开/关
			{
				p[j++] = 0;
			}
			else if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_RGBCW_HSB)//调色
			{
				p[j++] = 4;
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[0];
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[1];
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[2];
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[3];
			}
			else if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_RGBCW_CB)//调CW
			{
				p[j++] = 3;
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[0];
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[1];
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[2];
			}
			break;
		case DEVIC_TYPE_STANDARD_JCURTAIN://标准卷帘
		case DEVIC_TYPE_STANDARD_JCURTAIN_KNX://标准卷帘
		case DEVIC_TYPE_STANDARD_JCURTAIN1_ZIGBEE://Zigbee 标准卷帘
		case DEVIC_TYPE_STANDARD_JCURTAIN2_ZIGBEE://Zigbee 标准卷帘
		case DEVIC_TYPE_STANDARD_KCURTAIN://开合帘
		case DEVIC_TYPE_STANDARD_KCURTAIN_KNX://开合帘
		case DEVIC_TYPE_PUSH_WINDOW://标准型推窗机
		case DEVIC_TYPE_MECHANICAL_JOURNEY_JCURTAIN://机械行程卷帘
		case DEVIC_TYPE_ELECTRONIC_AUTO_JCURTAIN://电子自动卷帘
		case DEVIC_TYPE_ELECTRONIC_MANUAL_JCURTAIN://电子手动卷帘
		case DEVIC_TYPE_JOURNEY_JCURTAIN1_ZIGBEE://Zigbee行程卷帘
		case DEVIC_TYPE_JOURNEY_JCURTAIN2_ZIGBEE://Zigbee行程卷帘
		case DEVIC_TYPE_JOURNEY_JCURTAIN3_ZIGBEE://Zigbee行程卷帘
		case DEVIC_TYPE_CEILING_CURTAIN://天棚帘
		case DEVIC_TYPE_JOURNEY_KCURTAIN://行程开合帘
		case DEVIC_TYPE_JOURNEY_KCURTAIN_KNX://行程开合帘
		case DEVIC_TYPE_JOURNEY_KCURTAIN1_ZIGBEE://Zigbee行程开合帘
		case DEVIC_TYPE_JOURNEY_KCURTAIN2_ZIGBEE://Zigbee行程开合帘
		case DEVIC_TYPE_JOURNEY_KCURTAIN3_ZIGBEE://Zigbee行程开合帘
		case DEVIC_TYPE_ELECTRONIC_JOURNEY_BLIND://电子行程百叶帘
		case DEVIC_TYPE_MECHANICAL_JOURNEY_BLIND://机械行程百叶帘
		case DEVIC_TYPE_BLIND1_ZIGBEE://Zigbee 百叶帘
		case DEVIC_TYPE_BLIND2_ZIGBEE://Zigbee 百叶帘
		case DEVIC_TYPE_BLIND3_ZIGBEE://Zigbee 百叶帘
		case DEVIC_TYPE_MECHANICAL_PUSH_WINDOW://机械行程推窗机
		case DEVIC_TYPE_ELECTRONIC_PUSH_WINDOW://电子行程推窗机
		case DEVIC_TYPE_VERTICAL_CURTAIN://垂直帘
		case DEVIC_TYPE_SLIDING_DOOR://平移门
		case DEVIC_TYPE_PUSHPULL_WINDOW://推拉窗
		case DEVIC_TYPE_PUSHPULL_WINDOW1_ZIGBEE://Zigbee推窗机
		case DEVIC_TYPE_PUSHPULL_WINDOW2_ZIGBEE://Zigbee推窗机
		case DEVIC_TYPE_GROUP_ROUTE_MOTOR://行程灯组
		case DEVIC_TYPE_GROUP_ANGLE_MOTOR://角度灯组
		case DEVIC_TYPE_JOURNEY_JCURTAIN_KNX://行程卷帘
		case DEVIC_TYPE_DREAM_CURTAIN://梦幻帘
			p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Motor_Status.status;
			if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Motor_Status.status == CMD_MOTOR_OFF ||
				TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Motor_Status.status == CMD_MOTOR_ON ||
				TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Motor_Status.status == CMD_MOTOR_STOP)//开/关/停
			{
				p[j++] = 0;
			}
			else if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Motor_Status.status == CMD_MOTOR_ROUTE)//窗帘调到指定行程
			{
				p[j++] = 1;
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Motor_Status.route;
			}
			else if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Motor_Status.status == CMD_MOTOR_ANGLE)//窗帘调到指定角度(百叶帘)
			{
				p[j++] = 1;
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Motor_Status.angle;
			}
			break;
		case DEVIC_TYPE_WAZZOR_MOTOR://瓦瑟电机
			p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Motor_Status.status;
			if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Motor_Status.status == CMD_MOTOR_OFF ||
				TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Motor_Status.status == CMD_MOTOR_ON ||
				TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Motor_Status.status == CMD_MOTOR_STOP ||
				TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Motor_Status.status == CMD_MOTOR_DLYON)//开/关/停/开延时关
			{
				p[j++] = 0;
			}
			break;
		case DEVIC_TYPE_DALI_TIAOSE://DALI-RGB调色灯
			p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status;
			if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_OFF ||
				TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_ON)//开/关
			{
				p[j++] = 0;
			}
			else if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_RGBW)//调色
			{
				p[j++] = 3;
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[0];
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[1];
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[2];
			}
			else if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_DALIN_BRIGHTNESS)//
			{
				p[j++] = 1;
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[3];
			}
			break;
		case DEVIC_TYPE_DALI_RGBW://DALI-RGBW
			p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status;
			if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_OFF ||
				TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_ON)//开/关
			{
				p[j++] = 0;
			}
			else if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_RGBW)//调色
			{
				p[j++] = 4;
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[0];
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[1];
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[2];
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[3];
			}
			else if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_DALIN_BRIGHTNESS)//
			{
				p[j++] = 1;
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[4];
			}
			break;
		case DEVIC_TYPE_DALI_RGBCW://DALI-RGBCW
			p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status;
			if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_OFF ||
				TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_ON)//开/关
			{
				p[j++] = 0;
			}
			else if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_RGBW)//调色
			{
				p[j++] = 5;
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[0];
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[1];
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[2];
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[3];
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[4];
			}
			else if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_DALIN_BRIGHTNESS)//
			{
				p[j++] = 1;
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[5];
			}
			break;
		case DEVIC_TYPE_DALI_TIAOGUANG://DALI-调光灯
			p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status;
			if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_OFF ||
				TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_ON)//开/关
			{
				p[j++] = 0;
			}
			else if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_DALIN_BRIGHTNESS)//
			{
				p[j++] = 1;
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[0];
			}
			break;
		case DEVIC_TYPE_GROUP_DALI_TIAOSE://DALI-RGB调色灯
			p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status;
			if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_OFF ||
				TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_ON)//开/关
			{
				p[j++] = 0;
			}
			else if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_RGBW)//调色
			{
				p[j++] = 3;
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[0];
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[1];
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[2];
			}
			else if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_DALIN_BRIGHTNESS)//
			{
				p[j++] = 1;
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[3];
			}
			break;
		case DEVIC_TYPE_GROUP_DALI_RGBW://DALI-RGBW
			p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status;
			if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_OFF ||
				TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_ON)//开/关
			{
				p[j++] = 0;
			}
			else if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_RGBW)//调色
			{
				p[j++] = 4;
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[0];
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[1];
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[2];
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[3];
			}
			else if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_DALIN_BRIGHTNESS)//
			{
				p[j++] = 1;
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[4];
			}
			break;
		case DEVIC_TYPE_GROUP_DALI_RGBCW://DALI-RGBCW
			p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status;
			if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_OFF ||
				TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_ON)//开/关
			{
				p[j++] = 0;
			}
			else if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_RGBW)//调色
			{
				p[j++] = 5;
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[0];
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[1];
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[2];
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[3];
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[4];
			}
			else if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_DALIN_BRIGHTNESS)//
			{
				p[j++] = 1;
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[5];
			}
			break;
		case DEVIC_TYPE_GROUP_DALI_TIAOGUANG://DALI-调光灯
			p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status;
			if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_OFF ||
				TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_ON)//开/关
			{
				p[j++] = 0;
			}
			else if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.status == CMD_LIGHT_DALIN_BRIGHTNESS)//
			{
				p[j++] = 1;
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Light_Status.data[0];
			}
			break;
		case DEVIC_TYPE_CDOAS://新风
		case DEVIC_TYPE_LZT_CDOAS://梁志天新风
		case DEVIC_TYPE_CDOAS1_ZIGBEE://Zigbee新风
		case DEVIC_TYPE_CDOAS2_ZIGBEE://Zigbee新风
		case DEVIC_TYPE_CDOAS3_ZIGBEE://Zigbee新风
		case DEVIC_TYPE_GROUP_CDOAS://新风组
			p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Cdaos_Status.status;
			if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Cdaos_Status.status == CMD_CDOAS_ON ||
				TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Cdaos_Status.status == CMD_CDOAS_OFF)//开关
			{
				p[j++] = 0;
			}
			else if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Cdaos_Status.status == CMD_CDOAS_SETCO2)//设置CO2
			{
				p[j++] = 2;
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Cdaos_Status.Set_Value & 0xFF;
				p[j++] = (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Cdaos_Status.Set_Value>>8)&0xFF;
			}
			else if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Cdaos_Status.status == CMD_CDOAS_SETFAN)//设置风速
			{
				p[j++] = 1;
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Cdaos_Status.Cdaos_Status_Value.Byte.FanSpeed;
			}
			else if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Cdaos_Status.status == CMD_CDOAS_SETMODE)//设置模式
			{
				p[j++] = 1;
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Cdaos_Status.Mode;
			}
			break;
		case DEVIC_TYPE_HEAT://地暖
		case DEVIC_TYPE_LZT_HEAT://梁志天地暖
		case DEVIC_TYPE_HEAT1_ZIGBEE://Zigbee地暖
		case DEVIC_TYPE_HEAT2_ZIGBEE://Zigbee地暖
		case DEVIC_TYPE_HEAT3_ZIGBEE://Zigbee地暖
		case DEVIC_TYPE_GROUP_HEAT://地暖组
			p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Heat_Status.status;
			if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Heat_Status.status == CMD_HEAT_ON ||
				TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Heat_Status.status == CMD_HEAT_OFF)//开/关
			{
				p[j++] = 0;
			}
			else if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Heat_Status.status == CMD_HEAT_SETTEMP)//设置温度
			{
				p[j++] = 1;
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Heat_Status.Set_Temp;
			}
			break;
		case DEVIC_TYPE_AIRCONDITION://空调
		case DEVIC_TYPE_LZT_AIRCONDITION://梁志天空调
		//case DEVIC_TYPE_CODING_AIRCONDITION://编码型空调
		case DEVIC_TYPE_AIRCONDITION1_ZIGBEE://Zigbee空调
		case DEVIC_TYPE_AIRCONDITION2_ZIGBEE://Zigbee空调
		case DEVIC_TYPE_AIRCONDITION3_ZIGBEE://Zigbee空调
		case DEVIC_TYPE_AIRCONDITION4_ZIGBEE://Zigbee空调
		case DEVIC_TYPE_GROUP_AIRCONDITION://空调组
			p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Air_Status.status;
			if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Air_Status.status == CMD_AIR_ON ||
				TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Air_Status.status == CMD_AIR_OFF)//开/关
			{
				p[j++] = 0;
			}
			else if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Air_Status.status == CMD_AIR_SETTEMP)//设置温度
			{
				p[j++] = 1;
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Air_Status.Set_Temp;
			}
			else if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Air_Status.status == CMD_AIR_SETMODE)//设置模式
			{
				p[j++] = 1;
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Air_Status.Air_Status_Value.Byte.Mode;
			}
			else if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Air_Status.status == CMD_AIR_SETFAN)//设置风速
			{
				p[j++] = 1;
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Air_Status.Air_Status_Value.Byte.Speed;
			}
			else if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Air_Status.status == CMD_AIR_SETFANX)//设置风向
			{
				p[j++] = 1;
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Air_Status.FanXiang.vol;
			}
			break;
		case DEVIC_TYPE_MATCH_CODE_AIRCONDITION://对码型空调
			p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Matching_Air_Status.status;
			if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Matching_Air_Status.status == CMD_AIR_ON ||
				TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Matching_Air_Status.status == CMD_AIR_OFF)//开/关
			{
				p[j++] = 0;
			}
			else if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Matching_Air_Status.status == CMD_AIR_SETTEMP)//设置温度
			{
				p[j++] = 1;
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Matching_Air_Status.Set_Temp;
			}
			else if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Matching_Air_Status.status == CMD_AIR_SETMODE)//设置模式
			{
				p[j++] = 1;
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Matching_Air_Status.Set_Mode;
			}
			else if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Matching_Air_Status.status == CMD_AIR_SETFAN)//设置风速
			{
				p[j++] = 1;
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Matching_Air_Status.Set_Speed;
			}
			else if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Matching_Air_Status.status == CMD_AIR_SETFANX)//设置风向
			{
				p[j++] = 1;
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Matching_Air_Status.FanXiang.vol;
			}
			break;
			break;
		case DEVIC_TYPE_DX_HEAT://德信地暖
			p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_DX_Heat_Status.status;
			if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_DX_Heat_Status.status == CMD_CAPILLARY_AIR_ON ||
				TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_DX_Heat_Status.status == CMD_CAPILLARY_AIR_OFF)//开/关
			{
				p[j++] = 0;
			}
			else if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_DX_Heat_Status.status == CMD_CAPILLARY_AIR_SETTEMP)//设置温度
			{
				p[j++] = 2;
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_DX_Heat_Status.Set_Temp & 0xFF;
				p[j++] = (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_DX_Heat_Status.Set_Temp>>8) & 0xFF;
			}
			break;
		case DEVIC_TYPE_ZNZX_HEAT://中南中心地暖
			p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_ZNZX_Heat_Status.status;
			if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_ZNZX_Heat_Status.status == CMD_CAPILLARY_AIR_ON ||
				TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_ZNZX_Heat_Status.status == CMD_CAPILLARY_AIR_OFF)//开/关
			{
				p[j++] = 0;
			}
			else if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_ZNZX_Heat_Status.status == CMD_CAPILLARY_AIR_SETTEMP)//设置温度
			{
				p[j++] = 2;
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_ZNZX_Heat_Status.Set_Temp & 0xFF;
				p[j++] = (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_ZNZX_Heat_Status.Set_Temp >> 8) & 0xFF;
			}
			else if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_ZNZX_Heat_Status.status == CMD_CAPILLARY_AIR_SLEEPMODE)//设置温度
			{
				p[j++] = 1;
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_ZNZX_Heat_Status.Sleep_Mode;
			}
			break;
		case DEVIC_TYPE_GROUP_BACKMUSIC://背景音乐组
		case DEVIC_TYPE_THIRD_BACKMUSIC://第三方背景音乐
		case DEVIC_TYPE_DOOYA_BACKMUSIC://dooya背景音乐
		case DEVIC_TYPE_YODOR_BACKMUSIC://优达背景音乐
		case DEVIC_TYPE_BACKAUDIO_BACKMUSIC://泊声背景音乐
		case DEVIC_TYPE_BACKAUDIO_485_BACKMUSIC://泊声485背景音乐
		case DEVIC_TYPE_YIJIA_BACKMUSIC://亿佳背景音乐
		case DEVIC_TYPE_HOPE_BACKMUSIC:	//向往背景音乐
			p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Music_Status.status;
			if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Music_Status.status == CMD_MUSIC_ON	||
				TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Music_Status.status == CMD_MUSIC_OFF ||
				TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Music_Status.status == CMD_MUSIC_PLAY ||
				TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Music_Status.status == CMD_MUSIC_PAUSE ||
				TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Music_Status.status == CMD_MUSIC_BEFORE ||
				TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Music_Status.status == CMD_MUSIC_AFTER)//开/关/播放/暂停
			{
				p[j++] = 0;
			}
			else if (TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Music_Status.status == CMD_MUSIC_VOLUME)//设置音量
			{
				p[j++] = 1;
				p[j++] = TFT_Device_Cmd[DeviceKeyVol].IT_Dev_STatus_Value.IT_Music_Status.Volume;
			}
			break;
		default:
			break;
		}
	}
	Protocol_Tx_Data.DataLen = j;
	size = (sizeof(Protocol_Tx_Data)-DATA_SIZE_MAX) + Protocol_Tx_Data.DataLen;
	printf("Moorgen INFO :Command Device No.%d Data:", DeviceKeyVol);
	for (i = 0; i < j - 5; i++)
		printf("%02X ", Protocol_Tx_Data.myData[5 + i]);
	printf("\n");
	Mobus_Send_Data_Push((unsigned char *)&Protocol_Tx_Data, (size + 1), true, USART_RESEND_MAX);
}
//文件传输应答
void RS485_File_Transfer_Ack(uint8_t chl, uint8_t Fn, FILE_TRANSFER_EER error)
{
	uint8_t size, i, *p = Protocol_Tx_Data.myData;

	Protocol_Tx_Data.FrameControl = FRAME_File_Transfer_Ack;
	Protocol_Tx_Data.FrameNum_H = 0x00;	//帧序列高
	Protocol_Tx_Data.dAddress = 0x00;			//目标地址
	Protocol_Tx_Data.FrameNum_L = gFrameNum;	//帧序列低 
	Protocol_Tx_Data.NetID = Sys.Addr;
	Protocol_Tx_Data.Chl.bits.SubAddr = chl;		//设备子地址
	Protocol_Tx_Data.Chl.bits.ChlMax = 0;		//设备总数
	Protocol_Tx_Data.DataLen = 4;
	//数据
	*p++ = Fn;
	*p++ = (error == TRANSFER_OK) ? 0 : 1;
	*p++ = error;
	*p++ = 0;//预留
	size = (sizeof(Protocol_Tx_Data)-DATA_SIZE_MAX) + Protocol_Tx_Data.DataLen;
	Mobus_Send_Data_Push((unsigned char *)&Protocol_Tx_Data, (size + 1), true, USART_RESEND_MAX);
}
//查询设备状态（主函数接口）
void RS485GetDeviceState(void)
{
	uint8_t chl;
	if (RS485TxData.Stat == true)return;		//如果还在发数中
	if (MessageFlag[MSG_DEV_UPDATA_STAT] == ON)
	{
		MessageFlag[MSG_DEV_UPDATA_STAT] = OFF;
		RS485PanelSendData(0, 3, DevUpData[DEVIC_TYPE_PANEL_CHL].Data);
	}
	if (MessageFlag[MSG_HEAT_UPDATA_STAT] == ON)
	{
		MessageFlag[MSG_HEAT_UPDATA_STAT] = OFF;
		chl = DevicTypeNumToChl(DEVIC_TYPE_HEAT_CHL);
		RS485SendData(chl, 5, DevUpData[DEVIC_TYPE_HEAT_CHL].Data);
	}
	if (MessageFlag[MSG_AIR_UPDATA_STAT] == ON)
	{
		MessageFlag[MSG_AIR_UPDATA_STAT] = OFF;
		chl = DevicTypeNumToChl(DEVIC_TYPE_AIRCONDITION_CHL);
		RS485SendData(chl, 11, DevUpData[DEVIC_TYPE_AIRCONDITION_CHL].Data);
	}
	if (MessageFlag[MSG_CDOAS_UPDATA_STAT] == ON)
	{
		MessageFlag[MSG_CDOAS_UPDATA_STAT] = OFF;
		chl = DevicTypeNumToChl(DEVIC_TYPE_CDOAS_CHL);
		RS485SendData(chl, 11, DevUpData[DEVIC_TYPE_CDOAS_CHL].Data);
	}
	if (MessageFlag[MSG_GET_ALL_DEVICE_STATE] == ON)
	{
		MessageFlag[MSG_GET_ALL_DEVICE_STATE] = OFF;
		RS485_Get_AllTFTDeviceState();
	}
	if(MessageFlag[MSG_GET_DEVICE_STATE] == ON)//获取当前界面的设备状态
	{
		MessageFlag[MSG_GET_DEVICE_STATE] = OFF;
		if (TFT_Device[DisplayValue.TFT_Display_Device].DeviceEventType == 1)//设备
			RS485_Get_TFTDeviceState(DisplayValue.TFT_Display_Device);
	}
	if (MessageFlag[MSG_GET_DEVICE_CONFIG] == ON)//获取当前界面的设备参数
	{
		MessageFlag[MSG_GET_DEVICE_CONFIG] = OFF;
		if (TFT_Device[DisplayValue.TFT_Display_Device].DeviceEventType == 1)//设备
			RS485_Get_TFTDeviceConfig(DisplayValue.TFT_Display_Device,1,0x10);
	}
}
//状态更新
void RS485DeviceStateRenew(void)
{
	uint8_t temp[16];
	
	if (Sys.TypeChl & DEVIC_TYPE_PANEL_NET_CHL)
	{
		temp[0] = 0x01;
		temp[1] = Dev.LedRing_Switch;
		if (Dev.LedRing_Switch == ON)
			temp[2] = Dev.LedRing_Brightness;
		else
			temp[2] = 0;
		if (memcmp(DevUpData[DEVIC_TYPE_PANEL_CHL].Data, temp, 3))
		{
			memcpy(DevUpData[DEVIC_TYPE_PANEL_CHL].Data, temp, 3);
			MessageFlag[MSG_DEV_UPDATA_STAT] = ON;
		}
	}
	if (Sys.TypeChl & DEVIC_TYPE_HEAT_NET_CHL)
	{
		uint16_t nVal;
		temp[0] = (uint8_t)Heat.Switch;
		if (Heat.OccupyState == ON)
			temp[0] |= 0x80;
		else
			temp[0] &= 0x7f;
		temp[1] = Heat.AntiFreeze;		// 防冻
		temp[1] <<= 2;
		temp[1] += Heat_Config.byte.TimerEn;	 // 定时
		temp[1] <<= 4;
		//设置温度
		temp[2] = (uint8_t)(Heat.UserTemp * 2);
		//正常
		if (Dev.Current_Temp <= 0)
		{
			temp[3] = 0;
			temp[4] = 0;
		}
		else if (Dev.Current_Temp >= 100)
		{
			nVal = 1000;
			temp[3] = (uint8_t)nVal;
			temp[4] = (uint8_t)(nVal >> 8);
		}
		else
		{
			nVal = Dev.Current_Temp * 10;
			temp[3] = (uint8_t)nVal;
			temp[4] = (uint8_t)(nVal >> 8);
		}
		if (memcmp(DevUpData[DEVIC_TYPE_HEAT_CHL].Data, temp, 5))//状态改变
		{
			memcpy(DevUpData[DEVIC_TYPE_HEAT_CHL].Data, temp, 5);//数据赋值
			MessageFlag[MSG_HEAT_UPDATA_STAT] = ON;
		}
		if (DevUpData[DEVIC_TYPE_HEAT_CHL].Data[2] != temp[2])
			MessageFlag[MSG_SAVE_CHILD_HEAT_STATE] = ON;
	}
	if (Sys.TypeChl & DEVIC_TYPE_AIR_NET_CHL)
	{
		uint16_t nVal;
		temp[0] = (uint8_t)Air.Switch;
		if (Air.OccupyState == ON)
			temp[0] |= 0x80;
		else
			temp[0] &= 0x7f;
		if (Air.Mode>4 || Air.Mode == 0)
			temp[1] = 0;
		else
			temp[1] = Air.Mode;
		temp[1] <<= 2;
		if (Air.WindSpeed <= 3)
			temp[1] += Air.WindSpeed;
		temp[1] <<= 3;
		temp[2] = (uint8_t)(Air.UserTemp * 2);//设置温度
		//实时温度
		if (Dev.Current_Temp <= 0)
		{
			temp[3] = 0;
			temp[4] = 0;
		}
		else if (Dev.Current_Temp >= 100)
		{
			nVal = 1000;
			temp[3] = (uint8_t)nVal;
			temp[4] = (uint8_t)(nVal >> 8);
		}
		else
		{
			nVal = Dev.Current_Temp * 10;
			temp[3] = (uint8_t)nVal;
			temp[4] = (uint8_t)(nVal >> 8);
		}
		temp[5] = Air.Mode;
		temp[6] = Air.WindSpeed;
		temp[7] = (Air.VerWind << 4) + Air.LevelWind;
		temp[8] = 0xFF;
		temp[9] = 0xFF;
		temp[10] = Air.SeasonMode;
		if (memcmp(DevUpData[DEVIC_TYPE_AIRCONDITION_CHL].Data, temp, 11))
		{
			memcpy(DevUpData[DEVIC_TYPE_AIRCONDITION_CHL].Data, temp, 11);
			MessageFlag[MSG_AIR_UPDATA_STAT] = ON;
		}
		if (DevUpData[DEVIC_TYPE_AIRCONDITION_CHL].Data[1] != temp[1] ||
			DevUpData[DEVIC_TYPE_AIRCONDITION_CHL].Data[2] != temp[2] ||
			DevUpData[DEVIC_TYPE_AIRCONDITION_CHL].Data[5] != temp[5] ||
			DevUpData[DEVIC_TYPE_AIRCONDITION_CHL].Data[6] != temp[6] ||
			DevUpData[DEVIC_TYPE_AIRCONDITION_CHL].Data[7] != temp[7] ||
			DevUpData[DEVIC_TYPE_AIRCONDITION_CHL].Data[10] != temp[10])
			MessageFlag[MSG_SAVE_CHILD_AIR_STATE] = ON;
	}
	if (Sys.TypeChl & DEVIC_TYPE_CDOAS_NET_CHL)
	{
		uint16_t nVal;
		temp[0] = (uint8_t)Cdoas.Switch;
		if (Cdoas.OccupyState == ON)
			temp[0] |= 0x80;
		else
			temp[0] &= 0x7f;
		temp[1] = Cdoas.WindSpeed;
		temp[1] <<= 4;
		nVal = Get_Cdoas_Set_Value();
		temp[2] = (uint8_t)nVal;
		temp[3] = (uint8_t)(nVal >> 8);
		nVal = Get_Cdoas_Current_Value();
		temp[4] = (uint8_t)nVal;
		temp[5] = (uint8_t)(nVal >> 8);
		//实际温度
		if (Dev.Current_Temp <= 0)
		{
			temp[6] = 0;
			temp[7] = 0;
		}
		else if (Dev.Current_Temp >= 100)
		{
			nVal = 1000;
			temp[6] = (uint8_t)nVal;
			temp[7] = (uint8_t)(nVal >> 8);
		}
		else
		{
			nVal = Dev.Current_Temp * 10;
			temp[6] = (uint8_t)nVal;
			temp[7] = (uint8_t)(nVal >> 8);
		}
		temp[8] = 0xFF;
		temp[9] = 0xFF;
		temp[10] = Cdoas.Mode;
		if (memcmp(DevUpData[DEVIC_TYPE_CDOAS_CHL].Data, temp, 11))
		{
			memcpy(DevUpData[DEVIC_TYPE_CDOAS_CHL].Data, temp, 11);
			MessageFlag[MSG_CDOAS_UPDATA_STAT] = ON;
		}
		if (DevUpData[DEVIC_TYPE_CDOAS_CHL].Data[1] != temp[1] ||
			DevUpData[DEVIC_TYPE_CDOAS_CHL].Data[2] != temp[2] ||
			DevUpData[DEVIC_TYPE_CDOAS_CHL].Data[3] != temp[3] ||
			DevUpData[DEVIC_TYPE_CDOAS_CHL].Data[10] != temp[10])
			MessageFlag[MSG_SAVE_CHILD_CDOAS_STATE] = ON;
	}
}
//设置获取状态的消息标志(1s定时器）
void Set_State_MessageFlag_1s(void)
{
	static volatile uint8_t Get_State_Timer10s = 0;
	static volatile uint8_t Get_Config_Timer10s = 0;
	if (MessageFlag[MSG_GET_DEVICE_STATE_EN] == OFF)
		Get_State_Timer10s = 0;
	else
	{
		Get_State_Timer10s++;
		if (Get_State_Timer10s == 10)
		{
			Get_State_Timer10s = 0;
			MessageFlag[MSG_GET_DEVICE_STATE] = ON;
		}
	}

	if (MessageFlag[MSG_GET_DEVICE_CONFIG_EN] == OFF)
		Get_Config_Timer10s = 0;
	else
	{
		Get_Config_Timer10s++;
		if (Get_Config_Timer10s == 10)
		{
			Get_Config_Timer10s = 0;
			MessageFlag[MSG_GET_DEVICE_CONFIG] = ON;
		}
	}
}
//===================================<接收帧处理>=======================================
#define FRAME_REQUEST_HEAD_LEN				10
uint8_t DataArry[USART_RXDATA_LEN];				//处理数据缓存
uint8_t UsartRxTempCount;						//处理数据长度
uint8_t MyInfoBuf[USART_RXDATA_LEN];			//主机读写数据缓存
#define CMD_VERSION						0X00	//版本信息
volatile bool EnterIntoResetMode;				//准备恢复出厂模式标记

//广播报文
void HandleFrameBroadcast(void)
{
	uint16_t size;
	size = FRAME_HEAD_LEN + DataArry[FRAME_HEAD_LEN - 1];
	if (size >= UsartRxTempCount)return;	//长度检查

	switch (DataArry[FRAME_HEAD_LEN - 2])//命令
	{
	case CMD_BROADCAST_STAT://查询状态
		break;
	case CMD_BROADCAST_EXIST://查询在线
		RS485PointSendReg();
		break;
	default:
		break;
	}
}
//命令帧处理
void HandleFrameCommand(void)
{
	uint16_t size;
	size = FRAME_HEAD_LEN + DataArry[FRAME_HEAD_LEN - 1];
	if (size >= UsartRxTempCount)return;	//长度检查

	switch (DataArry[FRAME_HEAD_LEN - 2])//命令
	{
	case CMD_ROUTE_STAT://查询状态
		break;
	case CMD_ROUTE_EXIST://查询在线
		RS485PointSendReg();
		break;
	default:
		break;
	}
}
//应答处理
void HandleFrameAsk(void)
{
	uint16_t  size;
	size = FRAME_HEAD_LEN + DataArry[FRAME_HEAD_LEN - 1];
	if (size >= UsartRxTempCount)return;	//长度检查

	switch (DataArry[FRAME_HEAD_LEN - 2])//命令
	{
	case SCMD_ASK://应答
		RS485SendProcessStop();//停止发送进程
		break;
	default:
		break;
	}
}
//请求帧处理
void HandleFrameRequest(void)
{
	return;//无
}
//数据帧处理
void HandleFrameData(void)
{
	uint8_t typeNum = 0, chl = 0, Cmd, DataLen;
	uint8_t *CmdData;
	uint16_t size;

	size = FRAME_HEAD_LEN + DataArry[FRAME_HEAD_LEN - 1];
	if (size >= UsartRxTempCount)return;	//长度检查

	chl = DataArry[5] & 0x0f;	//通道
	if (chl >= DEVICE_CHANNEL_MAX)return;

	typeNum = Sys.TypeChlNum[chl];//通道类型
	if (typeNum >= DEVICE_CHANNEL_MAX)return;

	printf("Moorgen INFO : Deal Data[0x%02X]\n", DataArry[0]);

	DataLen = DataArry[FRAME_HEAD_LEN - 1];	//数据长度（包括cmd）
	Cmd = DataArry[FRAME_HEAD_LEN];
	CmdData = &DataArry[FRAME_HEAD_LEN + 1];
	if (typeNum == DEVIC_TYPE_PANEL_CHL)
	{
		if (Cmd == 0x03)//屏保预览
		{
			Sys_Config.byte.Null = CmdData[0];//变量暂用
			MessageFlag[MSG_SCREENSAVER_PREVIEW] = ON;
			ituSceneSendEvent(&theScene, EVENT_CUSTOM_SCREENSAVER, "0");
		}
		else if (Cmd == 0x04)//氛围灯开关
		{
			Dev.LedRing_Switch = CmdData[0];
			MessageFlag[MSG_SAVE_NOWDATA] = ON;
			MessageFlag[MSG_DEV_UPDATA_STAT] = ON;
		}
		else if (Cmd == 0x05)//氛围灯亮度
		{
			Dev.LedRing_Brightness = CmdData[0];
			Dev.LedRing_Switch = 0x01;
			MessageFlag[MSG_SAVE_NOWDATA] = ON;
			MessageFlag[MSG_DEV_UPDATA_STAT] = ON;
		}
	}
	else
	{
		//通用
		if (Cmd == CMD_OCCUPY_ENABLE)//设备占用,CMD:0x67
		{
			if (typeNum == DEVIC_TYPE_HEAT_CHL)//地暖占用
			{
				Heat_After_Occupy = Heat;		//占用前状态赋值
				Heat.OccupyState = ON;			//打开占用标志
				MessageFlag[MSG_HEAT_UPDATA_STAT] = ON;//上报状态
			}
			else if (typeNum == DEVIC_TYPE_AIRCONDITION_CHL)//温控器0占用
			{
				Air_After_Occupy = Air;			//占用前状态赋值
				Air.OccupyState = ON;			//打开占用标志
				MessageFlag[MSG_AIR_UPDATA_STAT] = ON;//上报状态
			}
			else if (typeNum == DEVIC_TYPE_CDOAS_CHL)//新风0
			{
				Cdoas_After_Occupy = Cdoas;		//占用前状态赋值
				Cdoas.OccupyState = ON;			//打开占用标志
				MessageFlag[MSG_CDOAS_UPDATA_STAT] = ON;//上报状态
			}
		}
		else if (Cmd == CMD_OCCUPY_DISENABLE)//设备解除占用,CMD:0x68
		{
			if (typeNum == DEVIC_TYPE_HEAT_CHL && Heat.OccupyState == ON)//地暖解除占用
			{
				Heat = Heat_After_Occupy;//占用解除最后一条场景执行
				Heat.OccupyState = OFF;
				MessageFlag[MSG_HEAT_UPDATA_STAT] = ON;
			}
			else if (typeNum == DEVIC_TYPE_AIRCONDITION_CHL && Air.OccupyState == ON)//空调解除占用
			{
				Air = Air_After_Occupy;//占用解除最后一条场景执行
				Air.OccupyState = OFF;
				MessageFlag[MSG_AIR_UPDATA_STAT] = ON;
			}
			else if (typeNum == DEVIC_TYPE_CDOAS_CHL && Cdoas.OccupyState == ON)//新风解除占用
			{
				Cdoas = Cdoas_After_Occupy;//占用解除最后一条场景执行
				Cdoas.OccupyState = OFF;
				MessageFlag[MSG_CDOAS_UPDATA_STAT] = ON;
			}
		}
		else if (Cmd == CMD_ONOFF_REVERSE)// 反向,CMD:0x66
		{
			if (typeNum == DEVIC_TYPE_HEAT_CHL)//地暖0
			{
				if (Heat.OccupyState != ON)//非占用状态下，反向
				{
					if (Heat.Switch == ON)
						Heat.Switch = OFF;
					else
						Heat.Switch = ON;
				}
				else//占用状态，反向
				{
					if (Heat.Switch == ON)
						Heat_After_Occupy.Switch = OFF;
					else
						Heat_After_Occupy.Switch = ON;
				}
				MessageFlag[MSG_HEAT_UPDATA_STAT] = ON;//状态上报
			}
			else if (typeNum == DEVIC_TYPE_AIRCONDITION_CHL)//空调0
			{
				if (Air.OccupyState != ON)//非占用状态下，反向
				{
					if (Air.Switch == ON)
						Air.Switch = OFF;
					else
						Air.Switch = ON;
				}
				else//占用状态，反向
				{
					if (Air.Switch == ON)
						Air_After_Occupy.Switch = OFF;
					else
						Air_After_Occupy.Switch = ON;
				}
				MessageFlag[MSG_AIR_UPDATA_STAT] = ON;//状态上报
			}
			else if (typeNum == DEVIC_TYPE_CDOAS_CHL)//新风0
			{
				if (Cdoas.OccupyState != ON)//非占用状态下，反向
				{
					if (Cdoas.Switch == ON)
						Cdoas.Switch = OFF;
					else
						Cdoas.Switch = ON;
				}
				else//占用状态，反向
				{
					if (Cdoas.Switch == ON)
						Cdoas_After_Occupy.Switch = OFF;
					else
						Cdoas_After_Occupy.Switch = ON;
				}
				MessageFlag[MSG_CDOAS_UPDATA_STAT] = ON;//状态上报
			}
		}
		else
		{
			if (typeNum == DEVIC_TYPE_HEAT_CHL)//地暖
				Set_Heat_State(&DataArry[FRAME_HEAD_LEN], DataLen);
			else if (typeNum == DEVIC_TYPE_AIRCONDITION_CHL)//温控器
				Set_Air_State(&DataArry[FRAME_HEAD_LEN], DataLen);
			else if (typeNum == DEVIC_TYPE_CDOAS_CHL) //新风
				Set_Cdoas_State(&DataArry[FRAME_HEAD_LEN], DataLen);
		}
	}
}
//配置参数
void HandleFrameConfig(uint16_t addr)
{
	bool modFlag = false;
	uint8_t chl = 0, typeNum = 0xff, i, j;
	uint16_t size, nType = 0;
	uint32_t n;

	size = FRAME_HEAD_LEN + DataArry[FRAME_HEAD_LEN - 1];
	if (size >= UsartRxTempCount)return;	//长度检查	 
	chl = DataArry[5] & 0x0f;	//通道

	if (MessageFlag[MSG_SET_ADDR_TIME_OVER] == ON)
	{
		if ((addr == 0XFF) && (DataArry[1] == 0XFF))
		{
			addr = Sys.Addr;
			MessageFlag[MSG_SET_ADDR_TIME_OVER] = OFF;
		}
	}

	if (addr == Sys.Addr)
	{
		if (DataArry[FRAME_HEAD_LEN] == 0xAA)//修改新地址
		{
			printf("Moorgen INFO : 主机对模块修改地址\n");
			Sys.Addr = DataArry[FRAME_HEAD_LEN + 3];
			modFlag = true;
		}
		if (DataArry[FRAME_HEAD_LEN + 1] == 0xAA)//更改类型
		{
			nType = DataArry[FRAME_HEAD_LEN + 4];
			nType <<= 8;
			nType += DataArry[FRAME_HEAD_LEN + 5];
			if ((DataArry[5] == 0x88) || chl>DEVICE_CHANNEL_MAX)
			{
				chl = 0;
			}
			switch (nType)
			{
			case DEVIC_TYPE_HEAT://地暖
			case DEVIC_TYPE_AIRCONDITION://温控器
			case DEVIC_TYPE_CDOAS://新风
				typeNum = DevicTypeToNum(nType);
				if (chl < DEVICE_CHANNEL_MAX && chl!=0)
				{
					//清除配置通道类型
					if (Sys.TypeChlNum[chl]<DEVICE_CHANNEL_MAX)//清通道类型标记
					{
						DevicTypeFlagClear(chl);
					}
					Sys.TypeChlNum[chl] = 0xff;//通道类型号
					//清除原该类型通道
					for (i = 1; i<DEVICE_CHANNEL_MAX; i++)
					{
						if (Sys.TypeChlNum[i] == typeNum)
						{
							DevicTypeFlagClear(i);
							Sys.TypeChlNum[i] = 0xff;
						}
					}
					//设置
					DevicTypeFlagSet(nType);
					Sys.TypeChlNum[chl] = typeNum;//通道类型号
				}
				modFlag = true;
				break;
			case 0xFFFF://设置为未配置
				if (chl != 0)
				{
					DevicTypeFlagClear(chl);
					Sys.TypeChlNum[chl] = 0XFF;//通道类型号
					modFlag = true;
				}

				/*通道存在标记与通道配置同步验证*/
				for (i = 0; i<DEVICE_CHANNEL_MAX; i++)
				{
					n = 0x01 << i;
					if (Sys.TypeChl & n)
					{
						for (j = 0; j<DEVICE_CHANNEL_MAX; j++)
						{
							if (Sys.TypeChlNum[j] == i)break;
						}
						if (j >= DEVICE_CHANNEL_MAX)
						{
							DevicTypeFlagClear(j);
						}
					}
				}
				break;
			default:
				break;
			}
			printf("Moorgen INFO : 主机对模块修改类型\n");
		}
		if (DataArry[FRAME_HEAD_LEN + 2] == 0xAA)//更改通道
		{
			printf("Moorgen INFO : 主机对模块修改通道\n");
			if ((DataArry[FRAME_HEAD_LEN + 6] <= DEVICE_CHANNEL_MAX) && (DataArry[FRAME_HEAD_LEN + 6] != 0))
			{
				Sys.Channal = DataArry[FRAME_HEAD_LEN + 6];

				for (i = Sys.Channal; i<DEVICE_CHANNEL_MAX; i++)
				{
					DevicTypeFlagClear(i);
					Sys.TypeChlNum[i] = 0XFF;//通道类型号
				}
				modFlag = true;
			}
		}
		if (modFlag == true)
		{
			MessageFlag[MSG_SAVE_SYS] = ON;//保存
			Air_Switch_Set(OFF);
			Heat_Switch_Set(OFF);
			Cdoas_Switch_Set(OFF);
			RS485PointSendReg();//请求帧
			MessageFlag[MSG_GET_TIME] = ON;
		}
		else
		{
			RS485PointSendReg();//请求帧
		}
	}

}
//TFT显示设备状态更新
void HandleFrameUpdateDeviceState(void)
{
	uint16_t size;
	uint8_t StateDataLen, OneDataLen, n, i, j;
	uint8_t tempDeviceConfigData[256] = { 0 };
	uint8_t Serial_Number[30], Serial_Size;
	//长度检测
	size = FRAME_HEAD_LEN + DataArry[FRAME_HEAD_LEN - 1];
	if (size >= UsartRxTempCount)return;

	printf("Moorgen INFO : Deal Data[0x%02X]\n", DataArry[0]);
	//开始解析数据
	if (DataArry[FRAME_HEAD_LEN] == 0x04)//设备参数
	{
		StateDataLen = DataArry[FRAME_HEAD_LEN - 1] - 1;
		n = 1;
		while (StateDataLen > 0)
		{
			OneDataLen = DataArry[FRAME_HEAD_LEN + n];
			if (OneDataLen > MG_DEVICE_STATE_MAX_LEN)break;
			memcpy(tempDeviceConfigData, &DataArry[FRAME_HEAD_LEN + n+1], OneDataLen);//数据段中的一段
			//根据设备ID得到设备序号,并赋值状态数据
			Serial_Size = GetKeyVolByID(tempDeviceConfigData, Serial_Number);
			for (j = 0; j < Serial_Size; j++)
			{
				memcpy((uint8_t*)&TFT_Device_State[Serial_Number[j]].IT_Dev_STatus_Value, &tempDeviceConfigData[4], OneDataLen - 4);
				printf("Moorgen INFO : Device No.%d State Data : ", Serial_Number[j]);
				for (i = 0; i < OneDataLen - 4; i++)
					printf("%02X ", TFT_Device_State[Serial_Number[j]].IT_Dev_STatus_Value.data[i]);
				printf("\n");
			}
			n += OneDataLen + 1;//获得下一段数据的下标
			StateDataLen -=(OneDataLen + 1);
		}
		MessageFlag[MSG_GUI_STATE_UPDATE] = ON;//GUI显示状态更新
	}
	else if (DataArry[FRAME_HEAD_LEN] == 0x08)//设备参数
	{
		StateDataLen = DataArry[FRAME_HEAD_LEN - 1] - 1;
		n = 1;
		while (StateDataLen > 0)
		{
			OneDataLen = DataArry[FRAME_HEAD_LEN + n];
			memcpy(tempDeviceConfigData, &DataArry[FRAME_HEAD_LEN + n + 1], OneDataLen);//数据段中的一段
			//根据设备ID得到设备序号(可能存在多个相同设备)
			Serial_Size = GetKeyVolByID(tempDeviceConfigData, Serial_Number);
			for (j = 0; j < Serial_Size; j++)
			{
				uint8_t Start_Addr = tempDeviceConfigData[4];
				uint8_t ConfigInfo_Len = tempDeviceConfigData[5];
				uint8_t *ConfigInfo = &tempDeviceConfigData[6];
				if (OneDataLen < 6 || ConfigInfo_Len + 6 != OneDataLen)
				{
					printf("Moorgen INFO : DataLen error! ConfigInfo_Len:%d OneDataLen:%d\n", ConfigInfo_Len, OneDataLen);
					break;
				}
				if (ConfigInfo_Len > 256 - Start_Addr)
					ConfigInfo_Len = 256 - Start_Addr;
				memcpy(&TFT_Device_State[Serial_Number[j]].IT_Dev_Config_Value.data[Start_Addr], ConfigInfo, ConfigInfo_Len);
				//printf("Moorgen INFO : Device No.%d Config Data : ", Serial_Number[j]);
				//for (i = 0; i < MG_DEVICE_CONFIG_MAX_LEN; i++)
				//	printf("%02X ", TFT_Device_State[Serial_Number[j]].IT_Dev_Config_Value.data[i]);
				//printf("\n");
			}
			n += OneDataLen + 1;//获得下一段数据的下标
			StateDataLen -= (OneDataLen + 1);
		}
		MessageFlag[MSG_GUI_STATE_UPDATE] = ON;//GUI显示状态更新
	}
}
//设置TFT显示的设备参数
void HandleFrameSetDeviceData(void)
{
	uint16_t size,nType,SetDataLen,OneSetDataLen;
	uint8_t DataKeyNameLen,m, n;
	uint8_t tempDeviceConfigData[256] = { 0 };
	
	//长度检测
	size = FRAME_HEAD_LEN + DataArry[FRAME_HEAD_LEN - 1];
	if (size >= UsartRxTempCount)return;
	//数据中类型检测
	nType = DataArry[FRAME_HEAD_LEN + 1];
	nType <<= 8;
	nType += DataArry[FRAME_HEAD_LEN];
	if (nType != DEVIC_TYPE_DEFAULT)return;
	//配置的最大设备数检测
	if (DataArry[FRAME_HEAD_LEN + 2] > DeviceNumMax)return;
	printf("Moorgen INFO : Deal Data[0x%02X]\n", DataArry[0]);
	//开始解析配置数据
	SetDataLen = DataArry[FRAME_HEAD_LEN - 1] - 2;//Data段中设置参数的长度		//54
	m = 2;
	n = 0;
	while (SetDataLen > 0)
	{
		printf("SetDataLen:%d    ", SetDataLen);
		if (DataArry[FRAME_HEAD_LEN + m + n + 1] == 1)//事件类型：设备
		{
			DataKeyNameLen = DataArry[FRAME_HEAD_LEN + m + n + 9];//名字长度
			OneSetDataLen = DataKeyNameLen + 10;//单个设备数据长度
			printf("Device OneSetDataLen:%d\n", OneSetDataLen);
		}
		else if (DataArry[FRAME_HEAD_LEN + m + n + 1] == 2 ||
			DataArry[FRAME_HEAD_LEN + m + n + 1] == 3 ||
			DataArry[FRAME_HEAD_LEN + m + n + 1] == 4)//事件类型：场景/序列/清洁模式
		{
			DataKeyNameLen = DataArry[FRAME_HEAD_LEN + m + n + 7];//名字长度
			OneSetDataLen = DataKeyNameLen + 8;//单个设备数据长度
			printf("Scene OneSetDataLen:%d\n", OneSetDataLen);
		}
		else
		{
			printf("EventType Error! %d\n", DataArry[FRAME_HEAD_LEN + m + n + 1]);
			break;
		}
		memcpy(tempDeviceConfigData, &DataArry[FRAME_HEAD_LEN + m + n], OneSetDataLen);
		n += OneSetDataLen;
		SetDataLen -= OneSetDataLen;//准备解析下一段数据
		//数据格式化
		if (OneSetDataLen > sizeof(Type_TFT_Device) - sizeof(bool))
			OneSetDataLen = sizeof(Type_TFT_Device) - sizeof(bool);
		memset((unsigned char *)&TFT_Device[tempDeviceConfigData[0]].DeviceKeyVol, 0, sizeof(Type_TFT_Device)-sizeof(bool));//清空
		memcpy((unsigned char *)&TFT_Device[tempDeviceConfigData[0]].DeviceKeyVol, (unsigned char *)tempDeviceConfigData, OneSetDataLen);//赋值设备参数
		//字符串长度合理化
		if (TFT_Device[tempDeviceConfigData[0]].DeviceEventType == 0x01)
		{
			TFT_Device[tempDeviceConfigData[0]].TFTSCEQ.TFT_Device.DeviceName[29] = 0;
			TFT_Device[tempDeviceConfigData[0]].TFTSCEQ.TFT_Device.DeviceNameLen = strlen(TFT_Device[tempDeviceConfigData[0]].TFTSCEQ.TFT_Device.DeviceName);
		}
		else
		{
			TFT_Device[tempDeviceConfigData[0]].TFTSCEQ.TFT_Scene.DeviceName[31] = 0;
			TFT_Device[tempDeviceConfigData[0]].TFTSCEQ.TFT_Scene.DeviceNameLen = strlen(TFT_Device[tempDeviceConfigData[0]].TFTSCEQ.TFT_Scene.DeviceName);
		}
		TFT_Device[tempDeviceConfigData[0]].DeviceIsAllocation = true;//标记设备已配置

		//打印相关信息
		printf("Moorgen INFO : TFT Config Device No.%d\n", tempDeviceConfigData[0]);
		printf("               DeviceIsAllocation : %d\n", TFT_Device[tempDeviceConfigData[0]].DeviceIsAllocation);
		printf("               Device EventType : %d\n", TFT_Device[tempDeviceConfigData[0]].DeviceEventType);
		if (TFT_Device[tempDeviceConfigData[0]].DeviceEventType == 0x01)
		{
			printf("               Device Addr : %08X\n", TFT_Device[tempDeviceConfigData[0]].TFTSCEQ.TFT_Device.DeviceID.Value);
			printf("               Device icon : %02X\n", TFT_Device[tempDeviceConfigData[0]].TFTSCEQ.TFT_Device.DeviceIcon);
			printf("               Device Type : %04X\n", TFT_Device[tempDeviceConfigData[0]].TFTSCEQ.TFT_Device.DeviceType);
			printf("               Device NameLen : %d\n", TFT_Device[tempDeviceConfigData[0]].TFTSCEQ.TFT_Device.DeviceNameLen);
			printf("               Device Name : %s\n", TFT_Device[tempDeviceConfigData[0]].TFTSCEQ.TFT_Device.DeviceName);
		}
		else
		{
			printf("               Device Addr : %08X\n", TFT_Device[tempDeviceConfigData[0]].TFTSCEQ.TFT_Scene.DeviceID.Value);
			printf("               Device icon : %02X\n", TFT_Device[tempDeviceConfigData[0]].TFTSCEQ.TFT_Scene.DeviceIcon);
			printf("               Device NameLen : %d\n", TFT_Device[tempDeviceConfigData[0]].TFTSCEQ.TFT_Scene.DeviceNameLen);
			printf("               Device Name : %s\n", TFT_Device[tempDeviceConfigData[0]].TFTSCEQ.TFT_Scene.DeviceName);
		}
	}

	MessageFlag[MSG_SAVE_DEVICE_DATA] = ON;//储存最新的设备属性
	MessageFlag[MSG_GUI_CONFIG_UPDATE] = ON;//GUI显示状态更新
}
//删除TFT显示的设备参数
void HandleFrameDelDeviceData(void)
{
	uint16_t size, nType;
	uint8_t i;
	size = FRAME_HEAD_LEN + DataArry[FRAME_HEAD_LEN - 1];
	//长度检测
	if (size >= UsartRxTempCount)return;
	//数据中类型检测
	nType = DataArry[FRAME_HEAD_LEN + 1];
	nType <<= 8;
	nType += DataArry[FRAME_HEAD_LEN];
	if (nType != DEVIC_TYPE_DEFAULT)return;
	printf("Moorgen INFO : Deal Data[0x%02X]\n", DataArry[0]);
	//开始解析配置数据
	if (DataArry[FRAME_HEAD_LEN + 2] == 1)//删除特定按键配置
	{
		for (i = 0; i < DataArry[FRAME_HEAD_LEN - 1] - 3; i++)
		{
			TFT_Device[DataArry[FRAME_HEAD_LEN + 3 + i]].DeviceIsAllocation = false;//设为未配置
			TFT_Device[DataArry[FRAME_HEAD_LEN + 3 + i]].DeviceEventType = 0;
			TFT_Device[DataArry[FRAME_HEAD_LEN + 3 + i]].DeviceKeyVol = i;
			TFT_Device[DataArry[FRAME_HEAD_LEN + 3 + i]].TFTSCEQ.TFT_Device.DeviceIcon = 0;
			TFT_Device[DataArry[FRAME_HEAD_LEN + 3 + i]].TFTSCEQ.TFT_Device.DeviceID.Value = 0;
			TFT_Device[DataArry[FRAME_HEAD_LEN + 3 + i]].TFTSCEQ.TFT_Device.DeviceType = 0xFFFF;
			TFT_Device[DataArry[FRAME_HEAD_LEN + 3 + i]].TFTSCEQ.TFT_Device.DeviceNameLen = 12;
			strcpy(TFT_Device[DataArry[FRAME_HEAD_LEN + 3 + i]].TFTSCEQ.TFT_Device.DeviceName, "暂未配置");
			memset(TFT_Device_State[DataArry[FRAME_HEAD_LEN + 3 + i]].IT_Dev_STatus_Value.data, 0, sizeof(TFT_Device_State[DataArry[FRAME_HEAD_LEN + 3 + i]].IT_Dev_STatus_Value.data));
			printf("Moorgen INFO : TFT Delete Device No.%d\n", DataArry[FRAME_HEAD_LEN + 3 + i]);
		}
	}
	else if (DataArry[FRAME_HEAD_LEN + 2] == 2)//删除所有按键设备
	{
		printf("Moorgen INFO : TFT Delete All Device.\n");
		for (i = 0; i <= DeviceNumMax; i++)
		{
			TFT_Device[i].DeviceIsAllocation = false;//设为未配置
			TFT_Device[i].DeviceEventType = 0;
			TFT_Device[i].DeviceKeyVol = i;
			TFT_Device[i].TFTSCEQ.TFT_Device.DeviceIcon = 0;
			TFT_Device[i].TFTSCEQ.TFT_Device.DeviceID.Value = 0;
			TFT_Device[i].TFTSCEQ.TFT_Device.DeviceType = 0xFFFF;
			TFT_Device[i].TFTSCEQ.TFT_Device.DeviceNameLen = 12;
			strcpy(TFT_Device[i].TFTSCEQ.TFT_Device.DeviceName, "暂未配置");
			memset(TFT_Device_State[i].IT_Dev_STatus_Value.data, 0, sizeof(TFT_Device_State[i].IT_Dev_STatus_Value.data));
		}
	}
	MessageFlag[MSG_SAVE_DEVICE_DATA] = ON;//储存最新的设备属性
	MessageFlag[MSG_GUI_CONFIG_UPDATE] = ON;//GUI显示状态更新
}
//主机读数据请求
void MasterReadInfo(void)
{
	uint16_t size;
	uint8_t i, len = 0;
	uint8_t addr = 0, rLen = 0, chl, typeNum = 0;

	size = FRAME_HEAD_LEN + DataArry[FRAME_HEAD_LEN - 1];
	if (size >= UsartRxTempCount)return;	//长度检查
	addr = DataArry[FRAME_HEAD_LEN];//起始地址
	rLen = DataArry[FRAME_HEAD_LEN + 1];//读取长度
	printf("Moorgen INFO : Deal Data[0x%02X]\n", DataArry[0]);
	chl = DataArry[5] & 0x0f;	//通道
	if (DataArry[5] == 0x88 || chl >= DEVICE_CHANNEL_MAX)
	{
		chl = 0x0f;
	}
	else
	{
		if (chl >= DEVICE_CHANNEL_MAX)
			return;
		typeNum = DevicChlToTypeNum(chl);
		if ((typeNum >= DEVICE_CHANNEL_MAX) && (addr != CMD_VERSION))
			return;
	}
	if (addr == CMD_VERSION)//读取版本信息
	{
		printf("Moorgen INFO : Read Version Information\n");
		MyInfoBuf[0] = CMD_VERSION;
		memcpy(&MyInfoBuf[1], SOFTWARE_VERSION, strlen(SOFTWARE_VERSION));
		//从机设置参数上报
		RS485SendInfo(chl, (strlen(SOFTWARE_VERSION) + 1), MyInfoBuf);
	}
	else
	{
		if (chl == 0x0f || typeNum == DEVIC_TYPE_PANEL_CHL)
		{
			MyInfoBuf[0] = addr;
			MyInfoBuf[1] = rLen;
			memcpy(&MyInfoBuf[2], (uint8_t*)&Sys_Config.ConfigTable[addr], rLen);
			RS485SendInfo(chl, (rLen + 2), MyInfoBuf);
		}
		else if (typeNum == DEVIC_TYPE_AIRCONDITION_CHL)
		{
			MyInfoBuf[0] = addr;
			MyInfoBuf[1] = rLen;
			memcpy(&MyInfoBuf[2], (uint8_t*)&Air_Config.ConfigTable[addr], rLen);
			RS485SendInfo(chl, (rLen + 2), MyInfoBuf);
		}
		else if (typeNum == DEVIC_TYPE_HEAT_CHL)
		{
			MyInfoBuf[0] = addr;
			MyInfoBuf[1] = rLen;
			memcpy(&MyInfoBuf[2], (uint8_t*)&Heat_Config.ConfigTable[addr], rLen);
			RS485SendInfo(chl, (rLen + 2), MyInfoBuf);
		}
		else if (typeNum == DEVIC_TYPE_CDOAS_CHL)
		{
			MyInfoBuf[0] = addr;
			MyInfoBuf[1] = rLen;
			memcpy(&MyInfoBuf[2], (uint8_t*)&Cdoas_Config.ConfigTable[addr], rLen);
			RS485SendInfo(chl, (rLen + 2), MyInfoBuf);
		}
	}
}
//主机写数据
void MasterWiterInfo(void)
{
	bool SysCongfigIsChanged = false;
	uint16_t size,i;
	uint8_t len = 0;
	uint8_t addr = 0, rLen = 0, chl, typeNum = 0;
	uint8_t TempData[sizeof(Sys_Config.ConfigTable)] = { 0xFF };
	size = FRAME_HEAD_LEN + DataArry[FRAME_HEAD_LEN - 1];
	if (size >= UsartRxTempCount)return;	//长度检查
	printf("Moorgen INFO : Deal Data[0x%02X]\n", DataArry[0]);
	addr = DataArry[FRAME_HEAD_LEN];//起始地址获取
	rLen = DataArry[FRAME_HEAD_LEN + 1];//写入长度获取
	if ((addr + rLen - 1) > (sizeof(Sys_Config.ConfigTable)))return;//写入长度超出参数表大小
	chl = DataArry[5] & 0x0f;	//通道解析
	if (chl >= DEVICE_CHANNEL_MAX)
	{
		chl = 0x0f;
	}
	else
	{
		typeNum = DevicChlToTypeNum(chl);
		if (typeNum >= DEVICE_CHANNEL_MAX)return;
	}
	if (DataArry[FRAME_HEAD_LEN] == CMD_VERSION)//写s版本信息
	{
		//不支持
	}
	else
	{
		if (chl == 0x0f || typeNum == DEVIC_TYPE_PANEL_CHL)
		{
			memcpy((void *)TempData, (void *)Sys_Config.ConfigTable, sizeof(Sys_Config.ConfigTable));//拷贝原有参数
			memcpy((void *)&Sys_Config.ConfigTable[addr], (void *)&DataArry[FRAME_HEAD_LEN + 2], rLen);//修改配置参数
			for (int i = 0; i < sizeof(Sys_Config.ConfigTable); i++)//比较数据
			{
				if (TempData[i] != Sys_Config.ConfigTable[i])
				{
					SysCongfigIsChanged = true;
					if (i == 0x05)//菜单类型切换
						MessageFlag[MSG_GUI_SWITCH_MAINMENU] = ON;
					else if (i == 0x07 || i == 0x06)//屏保切换
						MessageFlag[MSG_GUI_SWITCH_SCREENSAVER] = ON;
					else if (i >= 0x08 && i <= 0x11)//切换姓氏
						MessageFlag[MSG_GUI_SWITCH_SURNAME] = ON;
				}
			}
			if (SysCongfigIsChanged)
			{
				MessageFlag[MSG_SAVE_SYS_CONFIG] = ON;
				if (Sys_Config.byte.ScrollingTime == 0)
					Sys_Config.byte.ScrollingTime = 5;
			}
		}
		else if (typeNum == DEVIC_TYPE_AIRCONDITION_CHL)
		{
			AIR_CONFIG TempData = Air_Config;//拷贝原有参数
			memcpy((void *)&Air_Config.ConfigTable[addr], (void *)&DataArry[FRAME_HEAD_LEN + 2], rLen);//修改配置参数
			if (memcmp(TempData.ConfigTable[addr], Air_Config.ConfigTable[addr], rLen))
				MessageFlag[MSG_SAVE_CHILD_AIR_CONFIG] = ON;
		}
		else if (typeNum == DEVIC_TYPE_HEAT_CHL)
		{
			HEAT_CONFIG TempData = Heat_Config;//拷贝原有参数
			memcpy((void *)&Heat_Config.ConfigTable[addr], (void *)&DataArry[FRAME_HEAD_LEN + 2], rLen);//修改配置参数
			if (memcmp(TempData.ConfigTable[addr], Heat_Config.ConfigTable[addr], rLen))
				MessageFlag[MSG_SAVE_CHILD_HEAT_CONFIG] = ON;
		}
		else if (typeNum == DEVIC_TYPE_CDOAS_CHL)
		{
			CDOAS_CONFIG TempData = Cdoas_Config;//拷贝原有参数
			memcpy((void *)&Cdoas_Config.ConfigTable[addr], (void *)&DataArry[FRAME_HEAD_LEN + 2], rLen);//修改配置参数
			if (memcmp(TempData.ConfigTable[addr], Cdoas_Config.ConfigTable[addr], rLen))
				MessageFlag[MSG_SAVE_CHILD_CDOAS_CONFIG] = ON;
		}
	}
}
//时间同步请求
void DecSendCmdTimeCheck(void)
{
	static uint8_t GetTimeTimes = 0;
	if (RS485TxData.Stat == ON){ return; } //如果还在发数中
	if (MessageFlag[MSG_GET_TIME] == OFF)return;
	MessageFlag[MSG_GET_TIME] = OFF;
	MyInfoBuf[0] = 0x01;
	//请求数据
	printf("Moorgen INFO : Send get time cmd.\n");
	RS485ReadInfo(0, 1, MyInfoBuf);
	
	if (GetTimeTimes >= 12)//上电每隔10s获取一次时间，获取12次，确保时间是主机的云时间（2反正）
	{
		MessageFlag[MSG_HAVE_GET_TIME] = ON;
	}
	else
	{
		GetTimeTimes++;//获取时间次数
	}
}
//从机读数据请求
void SlaveReadInfo(void)
{
	uint16_t size;
	size = FRAME_HEAD_LEN + DataArry[FRAME_HEAD_LEN - 1];
	if (size >= UsartRxTempCount)return;	//长度检查

	if (DataArry[FRAME_HEAD_LEN] == 0x01)
	{//时间同步
		mgSysTime.year = DataArry[FRAME_HEAD_LEN + 1] + 101;
		mgSysTime.mon = DataArry[FRAME_HEAD_LEN + 2];
		mgSysTime.day = DataArry[FRAME_HEAD_LEN + 3];
		mgSysTime.hour = DataArry[FRAME_HEAD_LEN + 4];
		mgSysTime.min = DataArry[FRAME_HEAD_LEN + 5];
		mgSysTime.sec = 0;
		printf("Moorgen INFO : Get Time: %d-%02d-%02d %02d:%02d:%02d\n", 
			mgSysTime.year-101+2000, 
			mgSysTime.mon,
			mgSysTime.day, 
			mgSysTime.hour, 
			mgSysTime.min, 
			mgSysTime.sec);
		Set_Sys_Time(mgSysTime);//设置时间
	}
}
//设备恢复出厂设置
void DeviceReset(void)
{
	uint16_t size;

	size = FRAME_HEAD_LEN + DataArry[FRAME_HEAD_LEN - 1];
	if (size >= UsartRxTempCount)return;	//长度检查
	if (DataArry[FRAME_HEAD_LEN] == 0x01)//进入恢复模式
	{
		EnterIntoResetMode = true;
	}
	else if (DataArry[FRAME_HEAD_LEN] == 0x02 && EnterIntoResetMode == true)
	{
		EnterIntoResetMode = false;
		ResetProcess();
	}
}
//恢复出厂超时检测(1s检测)
void ResetTimeOverCheck(void)
{
	static uint8_t TempTime = 0;
	if (EnterIntoResetMode == true)
	{
		TempTime++;
		if (TempTime == 60)//1分钟退出准备恢复模式
		{
			TempTime = 0;
			EnterIntoResetMode = false;
		}
	}
}
//恢复进程
void ResetProcess(void)
{
	RS485_Reset_ACK(1);//发送恢复成功应答
	MessageFlag[MSG_SAVE_RENEW] = ON;//执行恢复出厂
	usleep(1000 * 1000);//等待数据写入
	RS485PointSendReg(); //请求帧
}
//模块间同步数据处理
void HandleFrameSync(void)
{
	uint16_t size;
	uint8_t i, finded = 0;
	uint8_t serial_num = DataArry[3];
	static uint8_t serial_num_last = 0xAA;

	size = FRAME_HEAD_LEN + DataArry[FRAME_HEAD_LEN - 1];
	if (size >= UsartRxTempCount)return;	//长度检查

	if (serial_num_last == serial_num)return;//序列号判断
	serial_num_last = serial_num;

	for (i = 0; i<DataArry[FRAME_HEAD_LEN]; i++)
	{
		if (DataArry[FRAME_HEAD_LEN + 1 + i] == Sys.Addr)
		{
			finded = 1;
			break;
		}
	}
	if (finded)//有本模块地址
	{
		if (DataArry[5] == 0x01)//面板同步
		{
			//Sync_BackLight_Body = DataArry[FRAME_HEAD_LEN + DataArry[FRAME_HEAD_LEN] + 1];
		}
		else if (DataArry[5] == 0x02)//键值同步
		{
			//Slave_Panel.Addr = DataArry[FRAME_HEAD_LEN+DataArry[FRAME_HEAD_LEN]+1];
			//Slave_Panel.Chl = DataArry[FRAME_HEAD_LEN+DataArry[FRAME_HEAD_LEN]+2];
			//Slave_Panel.Key = DataArry[FRAME_HEAD_LEN+DataArry[FRAME_HEAD_LEN]+3];
			//Slave_Panel.Mode = DataArry[FRAME_HEAD_LEN+DataArry[FRAME_HEAD_LEN]+4];
			//Slave_Panel.Control_Timeover = ROTATE_CONTROL_TIME;
			//Dev.SetTimeCnt = LCD_LIGHT_TIME;//LED点亮
			//#if BODY_SENSOR
			//Body_SenSor.IsAnyBody = 1;
			//#endif
		}
		else if (DataArry[5] == 0x03)//传感器同步
		{
			float CurTemp;
			if (DataArry[FRAME_HEAD_LEN + DataArry[FRAME_HEAD_LEN] + 1] == 0x01 && DataArry[FRAME_HEAD_LEN + DataArry[FRAME_HEAD_LEN] + 2] == 2)//温度数据
			{
				CurTemp = (DataArry[FRAME_HEAD_LEN + DataArry[FRAME_HEAD_LEN] + 3] * 256) + DataArry[FRAME_HEAD_LEN + DataArry[FRAME_HEAD_LEN] + 4];
				CurTemp /= 10;
				if (Air_Config.byte.CurTemp_Source == 2)//温度来源总线传感器
				{
					printf("Moorgen INFO : Sensor data sync temperature:%f℃\n", CurTemp);
					Dev.Current_Temp = CurTemp;
				}
			}
		}
	}
}
//文件传输处理
void FileData_Recv(void)
{
	uint16_t size;
	uint8_t  chl;
	static uint8_t File_Name[32] = { 0 };	//文件名
	static uint8_t Photo_Num = 0;			//文件序号
	static uint32_t File_Size = 0;			//文件总大小
	static uint32_t File_CRC = 0;			//文件CRC32
	static uint16_t File_Pack_Num = 0;		//文件总段数
	static uint16_t Pack_Num = 0;			//上一包序号
	static uint8_t Trensfer_State = 0;		//传输状态（0：未开始，1：启动传输，2：传输中）
	static FILE_TRANSFER_CACHE Temp_Photo_File;
	uint8_t Fn = DataArry[FRAME_HEAD_LEN];
	size = FRAME_HEAD_LEN + DataArry[FRAME_HEAD_LEN - 1];
	if (size >= UsartRxTempCount)return;	//长度检查
	printf("Moorgen INFO : Deal Data[0x%02X]\n", DataArry[0]);
	chl = DataArry[5];	//通道

	if (Fn == 0x01)//启动文件传输
	{
		FILE_TRANSFER_DATA_HEAD *Data = &DataArry[FRAME_HEAD_LEN + 1];
		//清除所有缓存
		File_Size = 0;
		File_CRC = 0;
		File_Pack_Num = 0;
		Pack_Num = 0;
		Trensfer_State = 0;
		memset(File_Name, 0, sizeof(File_Name));
		memset(&Temp_Photo_File, 0, sizeof(Temp_Photo_File));
		
		if (Data->File_Attr == 2)//图片文件
		{
			uint8_t File_Name_Len, File_Suffix_Len;
			uint8_t *ptr;
			printf("Moorgen INFO : Start file transfer....\n");
			File_Pack_Num = Data->Segment_Total;
			File_Size = Data->File_Length;
			File_CRC = Data->File_CRC;
			//文件名
			File_Name_Len = *(uint8_t *)(Data + 1);
			ptr = ((uint8_t *)(Data + 1) + 1);
			memcpy(File_Name, ptr, File_Name_Len);
			File_Suffix_Len = *((uint8_t *)(Data + 1) + 1 + File_Name_Len);
			ptr = ((uint8_t *)(Data + 1) + 1 + File_Name_Len + 1);
			File_Name[File_Name_Len] = '.';
			memcpy(File_Name + File_Name_Len + 1, ptr, File_Suffix_Len);//后缀名
			char* str_location = strstr(File_Name, "pic_");
			if (str_location != NULL)
				Photo_Num = atoi(&str_location[4]);//图片序号
			Pack_Num = 0;//接收包清0
			printf("Moorgen INFO : File name : %s ,File size : %d ,File CRC32:%08X ,Transfer pack num:%d\n", File_Name, File_Size, File_CRC, File_Pack_Num);
			if (File_Size > PICTURE_MAX_SIZE)
			{
				printf("Moorgen INFO : Transfer file over maximum size !\n");
				RS485_File_Transfer_Ack(chl, Fn, TRANSFER_OTHER);
				return;
			}
			else if (Photo_Num > PICTURE_MAX_NUM || Photo_Num == 0)
			{
				printf("Moorgen INFO : Transfer file over maximum picture num !\n");
				RS485_File_Transfer_Ack(chl, Fn, TRANSFER_OTHER);
				return;
			}
			Trensfer_State = 1;//传输开始
			RS485_File_Transfer_Ack(chl, Fn, TRANSFER_OK);
			return;
		}
		printf("Moorgen INFO : Transfer file is not picture!\n");
		RS485_File_Transfer_Ack(chl, Fn, TRANSFER_OTHER);
	}
	else if (DataArry[FRAME_HEAD_LEN] == 0x02)//传输文件内容
	{
		FILE_TRANSFER_DATA_BODY *Data = &DataArry[FRAME_HEAD_LEN + 1];
		uint8_t temp_data[128] = { 0 };
		uint16_t Segment_Num, Segment_Size, Segment_CRC16, Calculate_CRC16;
		uint32_t Calculate_CRC32;
		Segment_Num = Data->Segment_Num;
		Segment_Size = (Data->Segment_Size > sizeof(temp_data)) ? sizeof(temp_data) : Data->Segment_Size;
		Segment_CRC16 = Data->Segment_CRC;
		if (strlen(File_Name) == 0 || File_Size == 0 || File_CRC == 0 || File_Pack_Num == 0 || Trensfer_State == 0)
		{
			printf("Moorgen INFO : No Transfer start data received!\n");
			RS485_File_Transfer_Ack(chl, Fn, TRANSFER_FORMAL_ERROR);
			return;
		}
		if (Segment_Num >= File_Pack_Num)
		{
			printf("Moorgen INFO : Segment_Num out of range!\n");
			RS485_File_Transfer_Ack(chl, Fn, TRANSFER_FORMAL_ERROR);
			return;
		}
		if (Trensfer_State == 1 && Segment_Num != 0)
		{
			printf("Moorgen INFO : Segment_Num Error! Trensfer step:%d, current Pack Num:%d\n", Trensfer_State, Segment_Num);
			RS485_File_Transfer_Ack(chl, Fn, TRANSFER_FORMAL_ERROR);
			return;
		}
		if (Trensfer_State == 2 && Segment_Num - Pack_Num > 1)
		{
			printf("Moorgen INFO : Segment_Num Jump Error! Trensfer step:%d, current Pack Num:%d\n", Trensfer_State, Segment_Num);
			RS485_File_Transfer_Ack(chl, Fn, TRANSFER_FORMAL_ERROR);
			return;
		}
		Trensfer_State = 2;//传输中
		Pack_Num = Segment_Num;//包序号
		memcpy(temp_data, (uint8_t *)(Data + 1), Segment_Size);
		Calculate_CRC16 = CRC16_XMODEM(temp_data, Segment_Size);
		if (Calculate_CRC16 == Segment_CRC16)//CRC通过
		{
			memcpy(&Temp_Photo_File.File_Data[Pack_Num * 128], temp_data, Segment_Size);
			printf("Moorgen INFO : Transfer normal...Trensfer step:%d, current Pack Num:%d, Segment_Size:%d\n", Trensfer_State, Segment_Num, Segment_Size);
		}
		else
		{
			printf("Moorgen INFO : File transfer false, CRC16 Error! Calculate CRC16:%04X  File CRC16:%04X\n", Calculate_CRC16, Segment_CRC16);
			RS485_File_Transfer_Ack(chl, Fn, TRANSFER_FORMAL_ERROR);
			return;
		}
		if (Segment_Num == (File_Pack_Num - 1))//最后一包
		{
			Calculate_CRC32 = CRC32(Temp_Photo_File.File_Data, File_Size);
			if (Calculate_CRC32 == File_CRC)//全文件CRC32校验
			{
				printf("Moorgen INFO : File transfer success, will save file.\n");
				memcpy(Temp_Photo_File.File_Name, File_Name, strlen(File_Name));
				Temp_Photo_File.File_CRC32 = File_CRC;
				Temp_Photo_File.File_Size = File_Size;
				//执行写入操作
				char temp_name[32] = { 0 };
				strcpy(temp_name, Temp_Photo_File.File_Name);
				char* str_location = strstr(temp_name, "pic_");
				char* point_location = strchr(temp_name, '.');
				if (str_location != NULL || point_location !=NULL)
				{
					printf("Moorgen INFO : Save file %s, Num %d.\n", Temp_Photo_File.File_Name, Photo_Num);
					memcpy(&Photo_File[Photo_Num - 1], &Temp_Photo_File, sizeof(FILE_TRANSFER_CACHE));
					//对应地址写入PNG图片文件
					MessageFlag[MSG_SAVE_PHOTO1_DATA + Photo_Num - 1] = ON;
					//WritePhotoData(number);
					//Image_file_write(Photo_Num, &Temp_Photo_File);
				}
				else
				{
					printf("Moorgen INFO : File name do not contain pic_x!.\n");
				}
			}
			else
			{
				printf("Moorgen INFO : File transfer false, CRC32 Error! Calculate CRC32:%08X  File CRC32:%08X\n", Calculate_CRC32, File_CRC);
				RS485_File_Transfer_Ack(chl, Fn, TRANSFER_FORMAL_ERROR);
				return;
			}
		}
		RS485_File_Transfer_Ack(chl, Fn, TRANSFER_OK);
	}
	else
	{
		RS485_File_Transfer_Ack(chl, Fn, TRANSFER_FORMAL_ERROR);
	}
}
//设备升级（需要接入外部升级储存设备）
void SystemUpdate(void)
{
#ifdef CFG_WATCHDOG_ENABLE
	ithPrintf("Reboot...\n");
	ithWatchDogEnable();
	ithWatchDogSetReload(0);
	ithWatchDogRestart();
#endif // CFG_WATCHDOG_ENABLE
}
//设备测试
void HandleFrameTest(void)
{
	uint16_t size;
	size = FRAME_HEAD_LEN + DataArry[FRAME_HEAD_LEN - 1];
	if (size >= UsartRxTempCount)return;	//长度检查
	printf("Moorgen INFO : Deal Data[0x%02X]\n", DataArry[0]);
	if (DataArry[FRAME_HEAD_LEN] == FRAME_Test &&
		DataArry[FRAME_HEAD_LEN + 1] == FRAME_Test &&
		DataArry[FRAME_HEAD_LEN + 2] == FRAME_Test)
	{
		MessageFlag[MSG_HARDWARE_TEST] = ON;
	}
}
//接收数据包处理
void RS485RxDataHandle(void)
{
	uint16_t dAddress;
	uint8_t  crcValu,i;

	//获取数据
	if (ReadAPacketFromRxBuf(DataArry, &UsartRxTempCount) == false)return;
	printf("Moorgen INFO : Deal Data: ");
	for (i = 0; i < UsartRxTempCount; i++)
	{
		printf("%02X ", DataArry[i]);
	}
	printf(", Data Len:%d\n", UsartRxTempCount);
	//处理
	if (UsartRxTempCount < FRAME_HEAD_LEN)
	{
		printf("Moorgen INFO : [%s]Data lenth error! Datalen = %d\n",__func__,UsartRxTempCount);
		return;//长度检查	
	}

	//crc	
	crcValu = Get_CRC8(DataArry, (uint8_t)(UsartRxTempCount - 1));
	if (DataArry[UsartRxTempCount - 1] != crcValu)
	{
		printf("Moorgen INFO : [%s]Data CRC error! Recv_CRC = %02X,Calculate_CRC = %02X\n",__func__,DataArry[UsartRxTempCount - 1],crcValu);
		return;//长度检查	
	}

	//地址检查
	dAddress = DataArry[2];
	if ((dAddress != Sys.Addr) && (dAddress != ADDRESS_Broadcast))//地址为设备地址或广播
	{
		printf("Moorgen INFO : [%s]Data address error! Recv_Address = %02X\n",__func__,dAddress,crcValu);
		return;
	}
	//帧类型
	switch (DataArry[0])
	{
	case FRAME_Configure:	//配置命令(0x08)
		printf("Moorgen INFO : Deal Data[0x%02X]\n", DataArry[0]);
		HandleFrameConfig(dAddress);
		break;
	case FRAME_Broadcast:	//广播命令(0x00)
		printf("Moorgen INFO : Deal Data[0x%02X]\n", DataArry[0]);
		HandleFrameBroadcast();
		break;
	case FRAME_Command:		//主机命令(0x01)
		printf("Moorgen INFO : Deal Data[0x%02X]\n", DataArry[0]);
		if (dAddress == Sys.Addr)HandleFrameCommand();
		break;
	case FRAME_Request:		//请求命令(0x02)
		printf("Moorgen INFO : Deal Data[0x%02X]\n", DataArry[0]);
		if (dAddress == Sys.Addr)HandleFrameRequest();
		break;
	case FRAME_Ask:			//应答命令(0x03)
		printf("Moorgen INFO : Deal Data[0x%02X]\n", DataArry[0]);
		if (dAddress == Sys.Addr)HandleFrameAsk();
		break;
	case FRAME_Data:		//数据命令(0x04)
		if (dAddress == Sys.Addr)HandleFrameData();
		break;
	case FRAME_MasterReadInfo://主机读数据请求(0x20)
		if (dAddress == Sys.Addr)MasterReadInfo();
		break;
	case FRAME_MasterWiterInfo://主机写数据(0x23)
		if (dAddress == Sys.Addr)MasterWiterInfo();
		break;
	case FRAME_SlaveReadInfo: //从机读数据请求(0x21)
		printf("Moorgen INFO : Deal Data[0x%02X]\n", DataArry[0]);
		if (dAddress == Sys.Addr)SlaveReadInfo();
		break;
	case FRAME_TFT_Config:	//液晶面板设备状态数据
		if (dAddress == Sys.Addr); HandleFrameUpdateDeviceState();
		break;
	case FRAME_TFT_DataSet://设备数据配置
		if (dAddress == Sys.Addr)HandleFrameSetDeviceData();
		break;
	case FRAME_TFT_DataDel://设备数据删除
		if (dAddress == Sys.Addr)HandleFrameDelDeviceData();
		break;
	case FRAME_Device_SYNC://模块同步报文
		HandleFrameSync();
		break;
	case FRAME_Reset:     //恢复出厂设置
		printf("Moorgen INFO : Deal Data[0x%02X]\n", DataArry[0]);
		if (dAddress == Sys.Addr)DeviceReset();
		break;
	case FRAME_File_Transfer_Req:     //文件传输请求
		if (dAddress == Sys.Addr)FileData_Recv();
		break;
	case FRAME_Program:     //设备升级
		printf("Moorgen INFO : Deal Data[0x%02X]\n", DataArry[0]);
		if (dAddress == Sys.Addr)SystemUpdate();
		while (1);
		break;
	case FRAME_Test:     //设备测试
		HandleFrameTest();
		break;
	default:
		break;
	}
}

//根据ID获取设备序号
uint8_t GetKeyVolByID(uint8_t *pID,uint8_t* Ret)
{
	uint32_t ID = 0;
	uint8_t KeyVol,i=0;

	ID += pID[3];
	ID <<= 8;
	ID += pID[2];
	ID <<= 8;
	ID += pID[1];
	ID <<= 8;
	ID += pID[0];
	for (KeyVol = 1; KeyVol <= DeviceNumMax; KeyVol++)
	{
		if (TFT_Device[KeyVol].TFTSCEQ.TFT_Device.DeviceID.Value == ID)
		{
			Ret[i++] = KeyVol;//检测是否有相同ID的设备
		}
	}
	return i;
}
//根据设备序号获取ID
UINT32 GetIDByKeyVol(uint8_t KeyVol)
{
	return TFT_Device[KeyVol].TFTSCEQ.TFT_Device.DeviceID;
}
//设备类型清除
void DevicTypeFlagClear(uint16_t chl)
{
	uint8_t TypeNum = 0xff;
	uint16_t NetChl;

	TypeNum = Sys.TypeChlNum[chl];
	if (TypeNum == 0xff)return;
	NetChl = 0x01 << TypeNum;
	Sys.TypeChl &= (~NetChl);
}
//设备类型设置
void DevicTypeFlagSet(uint16_t type)
{
	if (type == DEVIC_TYPE_DEFAULT)//温控器
	{
		if (!(Sys.TypeChl & DEVIC_TYPE_PANEL_NET_CHL))
			Sys.TypeChl |= DEVIC_TYPE_PANEL_NET_CHL;		//通道设备存在指示
	}
	else if (type == DEVIC_TYPE_AIRCONDITION)//温控器
	{
		if (!(Sys.TypeChl & DEVIC_TYPE_AIR_NET_CHL))
			Sys.TypeChl |= DEVIC_TYPE_AIR_NET_CHL;		//通道设备存在指示
	}
	else if (type == DEVIC_TYPE_HEAT)//地暖
	{
		if (!(Sys.TypeChl & DEVIC_TYPE_HEAT_NET_CHL))
			Sys.TypeChl |= DEVIC_TYPE_HEAT_NET_CHL;		//通道设备存在指示
	}
	else if (type == DEVIC_TYPE_CDOAS)//新风
	{
		if (!(Sys.TypeChl & DEVIC_TYPE_CDOAS_NET_CHL))
			Sys.TypeChl |= DEVIC_TYPE_CDOAS_NET_CHL;		//通道设备存在指示
	}
}
//通道->设备类型
uint16_t DevicChlToType(uint16_t chl)
{
	uint16_t type = 0xffff;
	if (chl >= DEVICE_CHANNEL_MAX)return type;

	switch (Sys.TypeChlNum[chl])
	{
	case DEVIC_TYPE_PANEL_CHL://液晶面板
		type = DEVIC_TYPE_DEFAULT;
		break;
	case DEVIC_TYPE_HEAT_CHL://地暖0
		type = DEVIC_TYPE_HEAT;
		break;
	case DEVIC_TYPE_AIRCONDITION_CHL://温控器0
		type = DEVIC_TYPE_AIRCONDITION;
		break;
	case DEVIC_TYPE_CDOAS_CHL://新风0
		type = DEVIC_TYPE_CDOAS;
		break;
	default:
		type = 0xffff;
		break;
	}
	return type;
}
//设备类型号->通道
uint8_t DevicTypeNumToChl(uint8_t TypeNum)
{
	uint8_t i, chl = 0xff;
	if (TypeNum >= DEVICE_CHANNEL_MAX)return chl;

	for (i = 0; i<DEVICE_CHANNEL_MAX; i++)
	{
		if (Sys.TypeChlNum[i] == TypeNum)
		{
			chl = i;
			break;
		}
	}
	return chl;
}
//通道 -> 设备类型号
uint8_t DevicChlToTypeNum(uint8_t chl)
{
	uint8_t TypeNum = 0xff;
	if (chl >= DEVICE_CHANNEL_MAX)return TypeNum;

	TypeNum = Sys.TypeChlNum[chl];

	return TypeNum;
}
//设备类型->类型号
uint8_t DevicTypeToNum(uint16_t type)
{
	uint8_t dNum = 0xff;

	if (type == DEVIC_TYPE_DEFAULT)//温控器
	{
		dNum = DEVIC_TYPE_PANEL_CHL;
	}
	else if (type == DEVIC_TYPE_AIRCONDITION)//温控器
	{
		dNum = DEVIC_TYPE_AIRCONDITION_CHL;
	}
	else if (type == DEVIC_TYPE_HEAT)//地暖
	{
		dNum = DEVIC_TYPE_HEAT_CHL;
	}
	else if (type == DEVIC_TYPE_CDOAS)//新风
	{
		dNum = DEVIC_TYPE_CDOAS_CHL;
	}
	return dNum;
}